/**
 @file sys_tsingma_datapath.c

 @date 2017-11-31

 @version v3.0

*/

/// TEMP COMMENT
/// datapath.c content :
///  #1, soft table creat/mapping/index
///  #2, datapath resource assign and maintain
///  #3, sup/serdes/datapath init

/****************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "ctc_error.h"
#include "ctc_port.h"
#include "sys_usw_chip.h"
#include "sys_usw_datapath.h"
#include "sys_usw_qos_api.h"
#include "sys_usw_mac.h"
#include "sys_usw_peri.h"
#include "sys_usw_dmps.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_mcu.h"
#include "sys_tmm_datapath.h"
#include "sys_tmm_mac.h"
#include "sys_tmm_serdes.h"
#include "drv_api.h"
#include "usw/include/drv_chip_ctrl.h"
#include "usw/include/drv_common.h"
#include "sys_usw_register.h"
#include "sys_tmm_mcu.h"

extern sal_file_t g_tm_dump_fp;
extern const uint8 g_dmps_dbg_sw;
sal_file_t g_tmm_serdes_init_dump_fp = NULL;
const uint8 g_serdes_dbg_sw = 0;

extern uint16 sys_usw_datapath_get_lport_with_chan(uint8 lchip, uint16 chan_id);

#define DRV_IOW_FIELD_NZ(lchip, memid, fieldid, value, ptr, inst, index) \
    DRV_IOW_FIELD(lchip, memid, fieldid, value, ptr) 

#define TSINGMA_DUMP_PRINT  if(g_dmps_dbg_sw && g_tm_dump_fp) sal_fprintf

#define DP_DEBUG_FUNCTION_CALLED_PRINT() \
    do \
    { \
        if ((NULL != g_tm_dump_fp) && (g_dmps_dbg_sw)) \
        {\
            sal_fprintf(g_tm_dump_fp, "------ %s called ----------------\n", __func__); \
        }\
    } \
    while(0)

#define DP_DEBUG_FUNCTION_RETURN_PRINT() \
    do \
    { \
        if ((NULL != g_tm_dump_fp) && (g_dmps_dbg_sw)) \
        {\
            sal_fprintf(g_tm_dump_fp, "------ %s return ----------------\n", __func__); \
        }\
    } \
    while(0)


#define TMM_SUP_RESET_CTL_ADDR              0x00051070

                                                 /*CPUMAC0 CPUMAC1 LOO0 LOO1 LOO2 LOO3 OAM  DMATX0 DMATX1*/
uint16 g_misc_wrr_weight[MISC_CHAN_ITEM_BUTT-2] = {100,    50,     200, 25,  200, 25,  100, 50,    50};

/*logic_serdes_id -> pcs_idx, mac_id, pcs_l_id*/
const sys_logic_lane_to_pcs_mac_map_t g_lane_2_pcs_mac_map[SYS_TMM_MAX_SERDES_NUM] =
{
    /************* DP0 start *************/
    /* TXQM0 HSS0, support QSGMII */
    {0,   0, 0},
    {1,   4, 0},
    {2,   8, 0},
    {3,  12, 0},
    {4,  16, 0},
    {5,  20, 0},
    {6,  24, 0},
    {7,  28, 0},
    /* TXQM0 HSS1, DO NOT support QSGMII */
    { 8,  32, 0},
    { 9,  33, 0},
    {10,  34, 0},
    {11,  35, 0},
    {12,  36, 0},
    {13,  37, 0},
    {14,  38, 0},
    {15,  39, 0},
    /* TXQM1 HSS2, support QSGMII */
    {0,  40, 0},
    {1,  44, 0},
    {2,  48, 0},
    {3,  52, 0},
    {4,  56, 0},
    {5,  60, 0},
    {6,  64, 0},
    {7,  68, 0},
    /* TXQM1 HSS3, DO NOT support QSGMII */
    { 8,  72, 0},
    { 9,  73, 0},
    {10,  74, 0},
    {11,  75, 0},
    {12,  76, 0},
    {13,  77, 0},
    {14,  78, 0},
    {15,  79, 0},
    /* TXQM2 HSS4, DO NOT support QSGMII */
    {0,  80, 0},
    {1,  81, 0},
    {2,  82, 0},
    {3,  83, 0},
    {4,  84, 0},
    {5,  85, 0},
    {6,  86, 0},
    {7,  87, 0},
    /* TXQM3 HSS5, DO NOT support QSGMII */
    {0, 120, 0},
    {1, 121, 0},
    {2, 122, 0},
    {3, 123, 0},
    {4, 124, 0},
    {5, 125, 0},
    {6, 126, 0},
    {7, 127, 0},
    /************* DP0 end *************/

    /************* DP1 start *************/
    /* TXQM0 HSS0, support QSGMII */
    {0, 160, 0},
    {1, 164, 0},
    {2, 168, 0},
    {3, 172, 0},
    {4, 176, 0},
    {5, 180, 0},
    {6, 184, 0},
    {7, 188, 0},
    /* TXQM0 HSS1, DO NOT support QSGMII */
    { 8, 192, 0},
    { 9, 193, 0},
    {10, 194, 0},
    {11, 195, 0},
    {12, 196, 0},
    {13, 197, 0},
    {14, 198, 0},
    {15, 199, 0},
    /* TXQM1 HSS2, support QSGMII */
    {0, 200, 0},
    {1, 204, 0},
    {2, 208, 0},
    {3, 212, 0},
    {4, 216, 0},
    {5, 220, 0},
    {6, 224, 0},
    {7, 228, 0},
    /* TXQM1 HSS3, DO NOT support QSGMII */
    { 8, 232, 0},
    { 9, 233, 0},
    {10, 234, 0},
    {11, 235, 0},
    {12, 236, 0},
    {13, 237, 0},
    {14, 238, 0},
    {15, 239, 0},
    /* TXQM2 HSS4, DO NOT support QSGMII */
    {0, 240, 0},
    {1, 241, 0},
    {2, 242, 0},
    {3, 243, 0},
    {4, 244, 0},
    {5, 245, 0},
    {6, 246, 0},
    {7, 247, 0},
    /* TXQM3 HSS5, DO NOT support QSGMII */
    {0, 280, 0},
    {1, 281, 0},
    {2, 282, 0},
    {3, 283, 0},
    {4, 284, 0},
    {5, 285, 0},
    {6, 286, 0},
    {7, 287, 0},
    /************* DP1 end *************/
};




extern sys_datapath_master_t* p_usw_datapath_master[];

extern int32 _sys_tmm_cmodel_datapath_init(uint8 board_type, uint8 datapath_type);

//extern int32
//sys_tmm_serdes_get_rate(uint8 mode, uint8 ovclk, uint8* p_width, uint8* p_div, uint8* p_speed);
extern int32 
sys_tmm_serdes_write_reg(uint8 lchip, uint16 serdes_id, uint16 addr, uint16 mask, uint16 data);
extern int32 
sys_tmm_serdes_read_reg(uint8 lchip, uint8 serdes_id, uint16 addr, uint16 mask, uint16 *data);
extern int32
sys_tmm_serdes_set_tx_taps(uint8 lchip, uint8 serdes_id, int8 *taps_param);
extern int32
sys_tmm_serdes_get_tx_taps(uint8 lchip, uint8 serdes_id, int8 *taps_param);
extern int32
sys_tmm_serdes_set_tx_prbs(uint8 lchip, ctc_chip_serdes_prbs_t *p_prbs);
extern int32
sys_tmm_serdes_get_tx_prbs(uint8 lchip, ctc_chip_serdes_prbs_t *p_prbs);
extern int32
sys_tmm_serdes_set_rx_prbs_check(uint8 lchip, ctc_chip_serdes_prbs_t *p_prbs);
extern int32
sys_tmm_serdes_get_rx_prbs_check(uint8 lchip, ctc_chip_serdes_prbs_t *p_prbs);
extern int32
sys_tmm_serdes_set_polarity(uint8 lchip, uint8 serdes_id, uint8 dir, uint8 val);
extern int32
sys_tmm_serdes_set_ctle(uint8 lchip, uint8 serdes_id, uint16 index, uint16 c1, uint16 c2);
extern int32
sys_tmm_serdes_get_ctle(uint8 lchip, uint8 serdes_id, uint16 *index, uint16 *c1, uint16 *c2);
extern int32
sys_tmm_serdes_fw_auto_ctle(uint8 lchip, uint8 serdes_id, uint8 is_auto);
extern int32
sys_tmm_serdes_get_eye(uint8 lchip, uint8 serdes_id, uint32 *eye_margin);
extern int32 
_sys_tmm_serdes_set_rx_tx_serial_loopback(uint8 lchip, uint8 serdes_id, uint8 enable);
extern int32 
sys_tmm_serdes_get_rx_tx_serial_loopback(uint8 lchip, uint8 serdes_id, uint8 *enable);
extern int32 
sys_tmm_serdes_get_tx_rx_serial_loopback(uint8 lchip, uint8 serdes_id, uint8 *enable);
extern int32
sys_tmm_serdes_fw_load_by_bcast(uint8 lchip, uint8 hss_id);
extern int32
sys_tmm_serdes_init_fw_header(uint8 lchip);
extern int32 
sys_tmm_serdes_is_correct_fw_loaded(uint8 lchip, uint8 serdes_id, uint8 *stat);
extern int32
sys_tmm_serdes_init(uint8 lchip, uint8 serdes_id, uint8 serdes_mode);
extern int32
_sys_tmm_serdes_set_datapath_prop(uint8 lchip, sys_tmm_serdes_datapath_prop_t prop_type, \
                                                     sys_tmm_serdes_datapath_prop_cfg_t *p_prop_cfg);
extern int32
_sys_tmm_serdes_get_datapath_prop(uint8 lchip, sys_tmm_serdes_datapath_prop_t prop_type, \
                                                     sys_tmm_serdes_datapath_prop_cfg_t *p_prop_cfg);
extern int32
sys_tmm_serdes_set_power_en(uint8 lchip, uint16 serdes_id, uint8 enable);
extern int32
sys_tmm_serdes_set_domain_reset(uint8 lchip, uint8 serdes_id, uint8 rst_type);
extern int32
sys_tmm_serdes_get_polarity(uint8 lchip, uint8 serdes_id, uint8 dir, uint8 *val);
extern int32
_sys_tmm_datapath_ipehdr_chanportmap(uint8 lchip, uint16 lport, uint8 chan);
extern int32
sys_tmm_get_lport_chan_map_by_logic_serdes(uint8 lchip, uint8 logic_serdes_id, uint8* p_chan, uint16* p_lport);
extern int32
_sys_tmm_dynamic_switch_serdes_cfg(uint8 lchip, uint8 phy_serdes_id, uint8 logic_serdes_id, uint8 src_mode, uint8 dst_mode, uint8 ovclk_flag);
extern int32 
sys_tmm_serdes_get_glb_info(uint8 lchip, uint8 physic_serdes_id, sys_tmm_serdes_glb_info_type_t type, uint8 *value);
extern int32
_sys_tmm_mac_get_fec_en(uint8 lchip, uint32 lport, uint32* p_value);
extern int32
sys_usw_port_set_property(uint8 lchip, uint32 gport, ctc_port_property_t port_prop, uint32 value);
extern int32
_sys_tmm_cpumac_sgmii_20T_clock_toggle(uint8 lchip, uint8 lport, sys_datapath_lport_attr_t* port_attr);
extern int32
sys_tmm_serdes_set_tx_en(uint8 lchip, uint8 serdes_id, uint8 enable);
int32
sys_tmm_serdes_get_tx_en(uint8 lchip, uint8 serdes_id, uint8* p_en);
extern int32
sys_tmm_mcu_serdes_loading(uint8 lchip, uint8 hss_iddq_flag[]);
extern int32
sys_tmm_serdes_get_real_data_rate(uint8 datarate_mode, uint8 overclock_flag, uint32 *real_data_rate);
extern int32
sys_tmm_flexe_check_serdes_bind_group(uint8 lchip, uint16 serdes_id, uint32 *is_bind);
extern int32
sys_tmm_serdes_get_phyready(uint8 lchip, uint8 physic_serdes_id, uint32* value);
extern int32
_sys_usw_mac_get_cl73_auto_neg(uint8 lchip, uint16 lport, uint32 type, uint32* p_value);
extern int32
sys_tmm_serdes_get_link_training_status(uint8 lchip, uint16 serdes_id, uint16* p_value);
extern int32
_sys_tmm_serdes_fw_config(uint8 lchip, sys_tmm_serdes_fw_config_param_t *p_data);
extern int32
sys_tmm_serdes_set_domain_reset1(uint8 lchip, uint8 serdes_id, uint8 rst_type);
extern int32
sys_tmm_serdes_set_domain_reset0(uint8 lchip, uint8 serdes_id, uint8 rst_type);
extern int32
sys_tmm_serdes_get_domain_reset(uint8 lchip, uint8 serdes_id, uint16* p_val);

/****************************************************************************
 *
* Defines and Macros
*
*****************************************************************************/
#define __DEBUG__

#define __MAPPING__

int32
sys_tmm_datapath_get_port_attr(uint8 lchip, uint16 lport, sys_datapath_lport_attr_t** port_attr)
{
    *port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
    if(NULL == (*port_attr))
    {
        return CTC_E_INVALID_PTR;
    }
    return CTC_E_NONE;
}

/*Get virtual txqm id by dp_chan_id. 
Virtual txqm id is NOT mac txqm id. It is used for ASIC internal algorithms. 
Mac-Chan mapping will not influence virtual txqm id.
It divides channel id in one DP into 5 parts based on dp_chan_id (channel id 
in single DP  0~127) value range:

dp_chan_id      | vtxqm | vtxqm_chan
----------------+---------------
  0~ 15         | 0     | 0~15
 16~ 31         | 1     | 0~15
 32~ 39, 48~ 79 | 2     | 0~ 7, 8~39
 40~ 47, 80~111 | 3     | 0~ 7, 8~39
112~127         | 4     | 0~15
*/
int32
_sys_tmm_datapath_get_virtual_txqm_chan(uint8 dp_chan_id, uint8* p_vtxqm, uint8* p_vtxqm_chan)
{
    uint8 vtxqm;
    uint8 vtxqm_chan;

    SYS_CONDITION_RETURN((SYS_TMM_CHANNEL_NUM_PER_DP <= dp_chan_id), CTC_E_INVALID_PARAM);

    if(15 >= dp_chan_id)
    {
        vtxqm      = 0;
        vtxqm_chan = dp_chan_id;
    }
    else if(31 >= dp_chan_id)
    {
        vtxqm      = 1;
        vtxqm_chan = dp_chan_id - 16;
    }
    else if(39 >= dp_chan_id)
    {
        vtxqm      = 2;
        vtxqm_chan = dp_chan_id - 32;
    }
    else if(47 >= dp_chan_id)
    {
        vtxqm      = 3;
        vtxqm_chan = dp_chan_id - 40;
    }
    else if(79 >= dp_chan_id)
    {
        vtxqm      = 2;
        vtxqm_chan = dp_chan_id - 40;
    }
    else if(111 >= dp_chan_id)
    {
        vtxqm      = 3;
        vtxqm_chan = dp_chan_id - 72;
    }
    else
    {
        vtxqm      = 4;
        vtxqm_chan = dp_chan_id - 112;
    }
    
    SYS_USW_VALID_PTR_WRITE(p_vtxqm,      vtxqm);
    SYS_USW_VALID_PTR_WRITE(p_vtxqm_chan, vtxqm_chan);
    
    return CTC_E_NONE;
}

/*
 * @brief       
 * @return      1 -- is flexe mode
 */
uint8 _sys_tmm_datapath_is_flexe_mode(uint8 lchip, uint8 dp_id)
{
    uint16 lport = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    uint16 mac_num_per_dp = SYS_TMM_MAX_MAC_NUM_PER_TXQM 
                                    * SYS_TMM_TXQM_NUM_PER_DP;

    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(NULL == port_attr);
        if(port_attr->mac_id % mac_num_per_dp != dp_id)
        {
            continue;
        }
        
        if(port_attr->interface_type == CTC_PORT_IF_FLEXE)
        {
            return TRUE;
        }
    }

    return FALSE;
}

int32
sys_tmm_datapath_get_chanid_by_lport(uint8 lchip, uint16 lport, uint8* p_chan_id)
{
    uint8  chan_id = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;

    ///TODO: FlexE channel id
    /*_sys_tmm_datapath_is_flexe_mode*/

    CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, lport, &port_attr));
    chan_id = (CTC_PORT_XPIPE_TYPE_6 == port_attr->xpipe_en) ? port_attr->pmac_chanid : port_attr->chan_id;
    SYS_USW_VALID_PTR_WRITE(p_chan_id, chan_id);

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_check_mode_valid(uint8 lchip, ctc_datapath_serdes_prop_t* p_serdes_raw)
{
    uint8 hss_id = SYS_TMM_MAP_SERDES_TO_HSS_IDX(p_serdes_raw->physical_serdes_id);
    uint8 logical_serdes_id = hss_id * SYS_TMM_LANE_NUM_PER_HSS + p_serdes_raw->logical_serdes_id;
    
    if(SYS_TMM_LANE_NUM_PER_HSS <= p_serdes_raw->group)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% logic lane id %u exceeds max value!\n", p_serdes_raw->group);
        return CTC_E_INVALID_PARAM;
    }

    /*QSGMII check*/
    if(((CTC_CHIP_SERDES_QSGMII_MODE == p_serdes_raw->mode) || (TMM_SERDES_DYN_ALLOW_ALL == p_serdes_raw->is_dynamic)) && 
       (!SYS_TMM_IS_LOGICAL_SERDES_SUPPORT_QSGMII(logical_serdes_id)))
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Serdes lane [hss_id %u, logical_serdes_id %u] cannot be QSGMII mode!\n", 
            hss_id, p_serdes_raw->logical_serdes_id);
        return CTC_E_NOT_SUPPORT;
    }

    /*TXQM0&1 do not support 200G/400G*/
    if(((CTC_CHIP_SERDES_CCG_R4_MODE == p_serdes_raw->mode) || (CTC_CHIP_SERDES_CDG_R8_MODE == p_serdes_raw->mode)) && 
        (32 > logical_serdes_id % SYS_TMM_MAX_SERDES_NUM_PER_DP))
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Serdes lane [hss_id %u, logical_serdes_id %u] cannot be 200G/400G mode!\n", 
            hss_id, p_serdes_raw->logical_serdes_id);
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_init_chan_2_logic_serdes_map(uint8 lchip, uint8 hss_id, uint8 lane_id, uint8 mode, 
                                        uint8 is_dyn, uint8* p_new_chan, uint8* p_chan_num)
{
    uint8 dp_id            = 0;
    uint8 alloc_num        = 1; //needing channel number, including in-use and idle reserve, 1 or 4
    uint8 chan_num         = 1; //in-use channel number, 0 or 1 or 4
    uint8 chan_idx         = 0;
    uint8 alloc_idx        = 0;
    uint8 new_chan         = 0; //return a new channel id (1st id if 4 channel needed)
    uint8 occupy_flag[4]   = {0};  //max length = alloc_num;
    uint8 arrange_type;
    uint8 lane_num;
    sys_resource_manage_item_info_t *p_channel_arrange = p_usw_datapath_master[lchip]->resource_manage.channel_arrange;

    if(TMM_SERDES_DYN_FORBID_ALL == is_dyn)
    {
        /*serdes in none mode and no dynamic switch, skip mapping to a lport*/
        SYS_CONDITION_RETURN(SYS_TMM_IS_MODE_NONE(mode), CTC_E_NONE);
        /*serdes in multi-lane mode and not lane 0, and no dynamic switch, skip mapping to a lport*/
        SYS_TMM_GET_LANE_NUM_BY_MODE(mode, lane_num);
        SYS_CONDITION_RETURN((0 != lane_id % lane_num), CTC_E_NONE);
    }

    /*1. decide alloc channel number*/
    if(((CTC_CHIP_SERDES_QSGMII_MODE == mode) || (TMM_SERDES_DYN_ALLOW_ALL == is_dyn)) && 
        SYS_TMM_HSS_SUPPORT_QSGMII(hss_id))
    {
        alloc_num = 4;
    }

    /*2. decide in-use chan number (port_num <= alloc_num)*/
    SYS_TMM_GET_CHAN_NUM_BY_MODE(mode, chan_num);

    /*3. decide occupy flags of allocated chan*/
    if(1 == alloc_num)
    {
        if(0 == chan_num)
        {
            /*(alloc 1, in-use 0) for non-1st lane, if it can switch to 1-lane mode, the occupy flag 0 is RESERVE*/
            occupy_flag[0] = SYS_CHAN_LPORT_OCCUPY_FREE;
        }
        else
        {
            /*(alloc 1, in-use 1) for 1st lane of its mode (multi-lane mode & single lane mode), the occupy flag 0 is IN_USE*/
            occupy_flag[0] = SYS_CHAN_LPORT_OCCUPY_IN_USE;
        }
    }
    else
    {
        if(0 == chan_num)
        {
            /*(alloc 4, in-use 0) for non-1st lane, if it can switch to QSGMII mode, the occupy flag 0~3 are RESERVE*/
            occupy_flag[0] = SYS_CHAN_LPORT_OCCUPY_FREE;
            occupy_flag[1] = SYS_CHAN_LPORT_OCCUPY_FREE;
            occupy_flag[2] = SYS_CHAN_LPORT_OCCUPY_FREE;
            occupy_flag[3] = SYS_CHAN_LPORT_OCCUPY_FREE;
        }
        else if(1 == chan_num)
        {
            /*(alloc 4, in-use 1) for 1st lane, if it can switch to QSGMII mode, the occupy flag 0 is IN_USE and 1~3 are RESERVE*/
            occupy_flag[0] = SYS_CHAN_LPORT_OCCUPY_IN_USE;
            occupy_flag[1] = SYS_CHAN_LPORT_OCCUPY_FREE;
            occupy_flag[2] = SYS_CHAN_LPORT_OCCUPY_FREE;
            occupy_flag[3] = SYS_CHAN_LPORT_OCCUPY_FREE;
        }
        else
        {
            /*(alloc 4, in-use 4) for QSGMII lane, the occupy flag 0~3 are IN_USE*/
            occupy_flag[0] = SYS_CHAN_LPORT_OCCUPY_IN_USE;
            occupy_flag[1] = SYS_CHAN_LPORT_OCCUPY_IN_USE;
            occupy_flag[2] = SYS_CHAN_LPORT_OCCUPY_IN_USE;
            occupy_flag[3] = SYS_CHAN_LPORT_OCCUPY_IN_USE;
        }
    }

    /*4. alloc new chan in g_chan_2_logic_serdes_map*/
    dp_id = SYS_TMM_GET_DP_ID_FROM_HSSID(hss_id);
    for(chan_idx = 0; chan_idx < SYS_TMM_LPORT_NUM_PER_DP; chan_idx++)
    {
        if(SYS_CHAN_LPORT_OCCUPY_RSV == p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][chan_idx].occupy_flag)
        {
            if(0 == alloc_idx)
            {
                new_chan = chan_idx + dp_id * SYS_TMM_LPORT_NUM_PER_DP;
            }

            /*skip misc channel*/
            arrange_type = p_channel_arrange[new_chan].arrange_type;
            if(SYS_BMP_IS_SET(arrange_type, SYS_BMP_TO_VAL_U8(SYS_ARRANGE_MISC_CHAN_BMP)))
            {
                continue;
            }
            
            p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][chan_idx].logic_serdes_id = 
                SYS_TMM_GET_SERDES_ID_BY_LANE(hss_id, lane_id);
            p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][chan_idx].occupy_flag     = 
                occupy_flag[alloc_idx];
            alloc_idx++;
            if(alloc_idx >= alloc_num)
            {
                break;
            }
        }
    }
    /*check if exceeds*/
    if(SYS_TMM_CHANNEL_NUM_PER_DP <= chan_idx)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " lport id exceeds max value! new_chan %u, chan_num %u, alloc_num %u\n", 
            new_chan, chan_num, alloc_num);
        return CTC_E_INVALID_CONFIG;
    }

    SYS_USW_VALID_PTR_WRITE(p_new_chan, new_chan);
    SYS_USW_VALID_PTR_WRITE(p_chan_num, chan_num);

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_extport_start_id(uint8 lchip, uint16* p_lport_start)
{
    uint16 lport = 0;
    uint8  arrange_type;

    if (TRUE != p_usw_datapath_master[lchip]->bpe_full_mode)
    {
        for(lport = SYS_DMPS_MISC_PORT_START; lport != 0; lport--)
        {
            SYS_CONDITION_RETURN(256 <= lport, CTC_E_INVALID_PARAM);
            arrange_type = p_usw_datapath_master[lchip]->resource_manage.lport_arrange[lport].arrange_type;
            
            SYS_CONDITION_BREAK(!SYS_BMP_IS_SET(arrange_type, SYS_BMP_TO_VAL_U8(SYS_ARRANGE_EXT_PORT_BMP)));
        }
        lport++;
    }
    SYS_USW_VALID_PTR_WRITE(p_lport_start, lport);

    return CTC_E_NONE;
}

/*Get lport from g_chan_2_logic_serdes_map*/
int32
_sys_tmm_datapath_alloc_lport(uint8 lchip, uint8 logic_serdes_id, uint16* p_chan_id, uint16* p_lport, uint8 port_num)
{
    uint8  exist_flag = FALSE;
    uint8  dp_id      = SYS_TMM_GET_DP_ID_FROM_SERDES(logic_serdes_id);
    uint16 dp_chan_id = 0;
    uint16 idx;
    uint16 lport;
    uint8  arrange_type;
    sys_resource_manage_item_info_t *p_lport_arrange   = p_usw_datapath_master[lchip]->resource_manage.lport_arrange;

    if(0 == port_num)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% invalid lport num %u\n", port_num);
        return CTC_E_INVALID_CONFIG;
    }

    if(1 < dp_id)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% invalid dp_id %u\n", dp_id);
        return CTC_E_INVALID_CONFIG;
    }

    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        if(p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].logic_serdes_id == logic_serdes_id)
        {
            exist_flag = TRUE;
            break;
        }
    }

    if((!exist_flag) || (SYS_TMM_CHANNEL_NUM_PER_DP <= dp_chan_id))
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% logic serdes id %u has no related lport!\n", logic_serdes_id);
        return CTC_E_INVALID_CONFIG;
    }

    if(SYS_CHAN_LPORT_OCCUPY_FREE != p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% channel[%u][%u] occupy_flag %u! logic serdes id %u\n", 
            dp_id, dp_chan_id, p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag, logic_serdes_id);
        return CTC_E_INVALID_CONFIG;
    }

    for(idx = 0; idx < port_num; idx++)
    {
        SYS_CONDITION_CONTINUE(127 < dp_chan_id+idx);
        lport = p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id+idx].lport;
        arrange_type = p_lport_arrange[lport].arrange_type;
        if(!SYS_BMP_IS_SET(arrange_type, SYS_BMP_TO_VAL_U8(SYS_ARRANGE_NETWORK_PORT_BMP)))
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% lport %u cannot work as network port! arrange_type %u\n", 
                lport, arrange_type);
            return CTC_E_INVALID_CONFIG;
        }
        if(SYS_RESOURCE_FREE != p_lport_arrange[lport].using_stat)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% lport %u is in use!\n", lport);
            return CTC_E_INVALID_CONFIG;
        }
        
        p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id+idx].occupy_flag = SYS_CHAN_LPORT_OCCUPY_IN_USE;
    }

    /*only 1st lport & chan will be return, no matter port_num is*/
    SYS_USW_VALID_PTR_WRITE(p_chan_id, SYS_GET_CHANNEL_BY_DP_CHANID(dp_chan_id, dp_id));
    SYS_USW_VALID_PTR_WRITE(p_lport, p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].lport);

    return CTC_E_NONE;
}

uint32
_sys_tmm_qmgr_speed_to_credit(uint16 speed)
{
    uint32 credit = 0;
    /* credit =(speed>=400)?40:(speed>=200)?30:... */
    switch(speed)
    {
        case 400:
            credit = 40;
            break;
        case 200:
            credit = 30;
            break;
        case 100:
            credit = 20;
            break;
        case 50:
            credit = 10;
            break;
        case 40:
            credit = 8;
            break;
        case 25:
        case 20:
            credit = 5;
            break;
        case 0:
            credit = 0;
            break;
        default:/*<=10G*/
            credit = 2;
            break;
    }
    return credit;

}




int32
sys_tmm_datapath_build_port_attr(uint8 lchip, sys_datapath_serdes_info_t* p_serdes)
{
    uint8  hss_id = SYS_TMM_MAP_SERDES_TO_HSS_IDX(p_serdes->physical_serdes_id);
    uint8  port_idx = 0;
    uint8  lane_num         = 0;
    uint16 lport            = 0;
    uint32 logic_serdes_id  = 0;
    int32  ret = CTC_E_NONE;
    uint32 speed_tmp = 0;
    uint32 credit =0;
    sys_datapath_lport_attr_t* port_attr = NULL;   
    if(0 == p_serdes->pcs_l_id)
    {
        logic_serdes_id = SYS_TMM_GET_SERDES_ID_BY_LANE(hss_id, p_serdes->lane_id);
        SYS_CONDITION_RETURN(SYS_MAX_PORT_NUM_PER_SERDES < p_serdes->port_num, CTC_E_INVALID_PARAM);
        SYS_CONDITION_RETURN(SYS_TMM_MAX_SERDES_NUM <= logic_serdes_id, CTC_E_INVALID_PARAM);
        for (port_idx = 0; port_idx < p_serdes->port_num; port_idx++)
        {
            lport = p_serdes->lport + port_idx;
            ret = sys_tmm_datapath_get_port_attr(lchip, lport, &port_attr);
            SYS_CONDITION_CONTINUE(CTC_E_NONE != ret);
            SYS_CONDITION_CONTINUE(SYS_TMM_IS_MODE_NONE(p_serdes->mode));
            SYS_TMM_GET_LANE_NUM_BY_MODE(p_serdes->mode, lane_num);
            port_attr->serdes_num                = lane_num;                                        //lane number
            port_attr->multi_serdes_id[p_serdes->pcs_l_id] = p_serdes->physical_serdes_id;                         //physical serdes id
            port_attr->pcs_idx                   = g_lane_2_pcs_mac_map[logic_serdes_id].pcs_idx;   //0~7 or 15
            port_attr->mac_id_reserve            = g_lane_2_pcs_mac_map[logic_serdes_id].mac_id + port_idx;        //0~159 in one DP, 0~319 in total
            if (!p_serdes->flexe_flag)
            {
                port_attr->mac_id                    = g_lane_2_pcs_mac_map[logic_serdes_id].mac_id + port_idx;    //0~159 in one DP, 0~319 in total
                port_attr->txqm_id                   = SYS_TMM_GET_TXQM_BY_MACID(port_attr->mac_id); //0~3 in one dp, 0~7 in total
                port_attr->internal_mac_idx          = SYS_TMM_GET_MACID_PER_TXQM(port_attr->mac_id);
            }
            else
            {
                port_attr->txqm_id                   = SYS_TMM_GET_TXQM_BY_MACID(port_attr->mac_id_reserve); //0~3 in one dp, 0~7 in total
                port_attr->internal_mac_idx          = SYS_TMM_GET_MACID_PER_TXQM(port_attr->mac_id_reserve);
            }
            port_attr->port_type                 = p_serdes->flexe_flag ? SYS_DMPS_INACTIVE_NETWORK_PORT : SYS_DMPS_NETWORK_PORT;
            port_attr->chan_id                   = p_serdes->chan_id + port_idx;
            port_attr->slice_id                  = 0;
            port_attr->pcs_mode                  = p_serdes->mode;
            port_attr->is_serdes_dyn             = p_serdes->is_dyn;                                //_tmm_serdes_isdyn_flag_t
            port_attr->an_fec                    = (1 << CTC_PORT_FEC_TYPE_RS)|(1 << CTC_PORT_FEC_TYPE_BASER);
            
            if((CTC_CHIP_SERDES_LG_MODE == p_serdes->mode) && (CTC_CHIP_SERDES_OCS_MODE_20_625G == p_serdes->overclocking_speed))
            {
                port_attr->speed_mode = CTC_PORT_SPEED_40G;
                port_attr->interface_type = CTC_PORT_IF_CR2;
            }
            else
            {
                SYS_TMM_GET_PORT_IFMODE_WITH_MODE(p_serdes->mode, port_attr->speed_mode, port_attr->interface_type);
            }
            SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed_tmp);
            credit = _sys_tmm_qmgr_speed_to_credit(speed_tmp);  
            port_attr->q_credit = (uint8)credit;
            /*recover an ability to default 0 when dynamic switch*/
            if(0 == port_attr->an_done_opr)
            {
                port_attr->an_ability.base_ability0  = 0;
                port_attr->an_ability.base_ability1  = 0;
                port_attr->an_ability.np0_ability0   = 0;
                port_attr->an_ability.np0_ability1   = 0;
                port_attr->an_ability.np1_ability0   = 0;
                port_attr->an_ability.np1_ability1   = 0;
            }
        }
    }
    else
    {
        lport = p_serdes->lport;
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, lport, &port_attr));
        SYS_CONDITION_RETURN(SYS_MAX_SERDES_NUM_PER_PORT <= p_serdes->pcs_l_id, CTC_E_INVALID_PARAM);
        port_attr->multi_serdes_id[p_serdes->pcs_l_id] = p_serdes->physical_serdes_id;
    }
    return CTC_E_NONE;
}

int32
sys_tmm_datapath_build_cpumac_port_attr(uint8 lchip, sys_datapath_serdes_info_t* p_serdes)
{
    uint8  lane_num  = 0;
    uint16 lport     = 0;
    uint32 speed_tmp = 0;
    uint32 credit    = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    sys_cpumac_mapping_t* p_cpumac_map = p_usw_datapath_master[lchip]->cpumac_map;

    /*check CpuMac valid*/
    SYS_CONDITION_RETURN(p_serdes->physical_serdes_id < SYS_TMM_CPUMAC_SERDES_START_ID, CTC_E_NONE);
    
    SYS_CONDITION_RETURN(SYS_TMM_IS_MODE_NONE(p_serdes->mode), CTC_E_NONE);

    if(0 == p_serdes->pcs_l_id)
    {
        lport = p_serdes->lport;
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, lport, &port_attr));

        SYS_TMM_GET_LANE_NUM_BY_MODE(p_serdes->mode, lane_num);
        port_attr->serdes_num                = lane_num;                                        //lane number
        port_attr->multi_serdes_id[p_serdes->pcs_l_id] = p_serdes->physical_serdes_id;          //physical serdes id
        /*mac_id, lport, chan_id and port_type is initialed in _sys_tmm_datapath_init_misc_info*/
        port_attr->pcs_idx                   = p_serdes->lane_id;   //0~3
        port_attr->mii_idx                   = p_serdes->lane_id;   //0~3
        port_attr->slice_id                  = 0;
        port_attr->pcs_mode                  = p_serdes->mode;
        port_attr->is_serdes_dyn             = p_serdes->is_dyn;                                //_tmm_serdes_isdyn_flag_t
        port_attr->an_fec                    = (1 << CTC_PORT_FEC_TYPE_RS)|(1 << CTC_PORT_FEC_TYPE_BASER);
        port_attr->txqm_id                   = SYS_TMM_CPUMAC_TXQM_ID;

        if(SYS_DMPS_RSV_PORT == port_attr->port_type)
        {
            port_attr->port_type = (p_cpumac_map[p_serdes->lane_id].is_network ? SYS_DMPS_CPUMAC_NETWORK_PORT : SYS_DMPS_CPU_MAC_PORT);
            port_attr->mac_id = p_cpumac_map[p_serdes->lane_id].mac_id;
            port_attr->chan_id = p_cpumac_map[p_serdes->lane_id].chan_id;
        }

        SYS_TMM_CPUMAC_GET_INTERNAL_MAC_ID(port_attr->mac_id, port_attr->internal_mac_idx);
        
        if((CTC_CHIP_SERDES_LG_MODE == p_serdes->mode) && (CTC_CHIP_SERDES_OCS_MODE_20_625G == p_serdes->overclocking_speed))
        {
            port_attr->speed_mode = CTC_PORT_SPEED_40G;
            port_attr->interface_type = CTC_PORT_IF_CR2;
        }
        else
        {
            SYS_TMM_GET_PORT_IFMODE_WITH_MODE(p_serdes->mode, port_attr->speed_mode, port_attr->interface_type);
        }

        SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed_tmp);
        credit = _sys_tmm_qmgr_speed_to_credit(speed_tmp);  
        port_attr->q_credit = (uint8)credit;
        /*recover an ability to default 0 when dynamic switch*/
        port_attr->an_ability.base_ability0  = 0;
        port_attr->an_ability.base_ability1  = 0;
        port_attr->an_ability.np0_ability0   = 0;
        port_attr->an_ability.np0_ability1   = 0;
        port_attr->an_ability.np1_ability0   = 0;
        port_attr->an_ability.np1_ability1   = 0;
    }
    else
    {
        lport = p_serdes->lport;
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, lport, &port_attr));
        SYS_CONDITION_RETURN(SYS_MAX_SERDES_NUM_PER_PORT <= p_serdes->pcs_l_id, CTC_E_INVALID_PARAM);
        port_attr->multi_serdes_id[p_serdes->pcs_l_id] = p_serdes->physical_serdes_id;
    }

    return CTC_E_NONE;
}



int32
_sys_tmm_datapath_clear_port_attr(uint8 lchip, uint16 lport)
{
    sys_datapath_lport_attr_t* port_attr = NULL;
    
    CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, lport, &port_attr));
    port_attr->port_type          = SYS_DMPS_RSV_PORT;
    port_attr->mac_id             = SYS_TMM_USELESS_ID16;
    port_attr->chan_id            = SYS_TMM_USELESS_ID8;
    port_attr->speed_mode         = CTC_PORT_SPEED_MAX;
    port_attr->slice_id           = 0;
    port_attr->serdes_num         = 0;
    port_attr->pcs_mode           = CTC_CHIP_MAX_SERDES_MODE;
    port_attr->serdes_id          = SYS_TMM_USELESS_ID8;
    port_attr->is_serdes_dyn      = 0;
    port_attr->is_first           = 0;
    port_attr->flag               = 0;
    port_attr->interface_type     = CTC_PORT_IF_MAX_TYPE;
    port_attr->an_fec             = 0;
    port_attr->code_err_count     = 0;
    port_attr->pcs_reset_en       = 0;
    port_attr->pcs_idx            = SYS_TMM_USELESS_ID8;
    port_attr->xpipe_en           = CTC_PORT_XPIPE_TYPE_0;
    port_attr->pmac_id            = SYS_TMM_USELESS_ID16;
    port_attr->emac_id            = SYS_TMM_USELESS_ID16;
    port_attr->pmac_chanid        = SYS_TMM_USELESS_ID8;
    port_attr->emac_chanid        = SYS_TMM_USELESS_ID8;
    port_attr->mutex_flag         = SYS_TMM_USELESS_ID8;
    port_attr->txqm_id            = SYS_TMM_USELESS_ID8;
    port_attr->q_credit           = SYS_TMM_USELESS_ID8;
    port_attr->an_done_opr        = FALSE;
    port_attr->internal_mac_idx   = SYS_TMM_USELESS_ID8;

    /* AN ability should be preset to 0 */
    port_attr->an_ability.base_ability0 = 0;
    port_attr->an_ability.base_ability1 = 0;
    port_attr->an_ability.np0_ability0  = 0;
    port_attr->an_ability.np0_ability1  = 0;
    port_attr->an_ability.np1_ability0  = 0;
    port_attr->an_ability.np1_ability1  = 0;
    port_attr->speed_value        = 0;
    port_attr->mac_id_reserve     = SYS_TMM_USELESS_ID16;
    port_attr->mac_id_aps         = SYS_TMM_USELESS_ID16;
    port_attr->client_bind_num    = 0;
    port_attr->flexe_mactx_encfg  = 0;
    port_attr->flexe_macrx_encfg  = 0;
    port_attr->flexe_en           = 0;
    port_attr->flexe_client       = 0;
    port_attr->flexe_client_aps   = 0;
    port_attr->an_speed_mode      = SYS_MAC_AN_SPEED_312D5M;
    port_attr->an_oc_backup       = 0;

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_port_attr_upt(uint8 lchip, sys_tmm_ds_target_attr_t* p_target, uint8 lport_idx)
{
    uint8  serdes_idx;
    uint8  idx;
    uint8  hss_id        = 0;
    uint8  inner_lane_id = 0;
    uint8  dp_id         = SYS_TMM_GET_DP_ID_FROM_LPORT(p_target->lport_list[lport_idx].lport);
    uint8  dp_chan_id    = SYS_TMM_GET_CHANN_PER_DP(p_target->lport_list[lport_idx].chan_id);
    uint16 tmp_lport;
    sys_datapath_hss_attribute_t* p_hss_vec = NULL;
    sys_resource_manage_item_info_t *p_lport_arrange = p_usw_datapath_master[lchip]->resource_manage.lport_arrange;

    switch(p_target->lport_list[lport_idx].upt_flag)
    {
        case SYS_DS_LPORT_DROP:
            CTC_ERROR_RETURN(_sys_tmm_datapath_clear_port_attr(lchip, p_target->lport_list[lport_idx].lport));
            if(SYS_TMM_CPUMAC_HSS_ID != hss_id)
            {
                /*set OCCUPY_FREE*/
                p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag = SYS_CHAN_LPORT_OCCUPY_FREE;
                tmp_lport = p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].lport;
                p_lport_arrange[tmp_lport].using_stat = SYS_RESOURCE_FREE;
            }
            break;
        case SYS_DS_LPORT_ADD:
        case SYS_DS_LPORT_REMAIN:
        default:
            for(idx = 0; idx < p_target->lport_list[lport_idx].serdes_relate_num; idx++)
            {
                SYS_CONDITION_CONTINUE(SYS_DS_LPORT_SERDES_OLD == p_target->lport_list[lport_idx].serdes_relate[idx].relate_flag);
                serdes_idx = p_target->lport_list[lport_idx].serdes_relate[idx].serdes_list_idx;
                hss_id = SYS_TMM_MAP_SERDES_TO_HSS_IDX(p_target->serdes_list[serdes_idx].logic_serdes_id);
                p_hss_vec = ctc_vector_get(p_usw_datapath_master[lchip]->p_hss_vector, hss_id);
                SYS_CONDITION_CONTINUE(NULL == p_hss_vec);
                inner_lane_id = SYS_TMM_MAP_SERDES_TO_LANE_ID(p_target->serdes_list[serdes_idx].logic_serdes_id);
                if(SYS_TMM_CPUMAC_HSS_ID == hss_id)
                {
                    CTC_ERROR_RETURN(sys_tmm_datapath_build_cpumac_port_attr(lchip, &(p_hss_vec->serdes_info[inner_lane_id])));
                }
                else
                {
                    CTC_ERROR_RETURN(sys_tmm_datapath_build_port_attr(lchip, &(p_hss_vec->serdes_info[inner_lane_id])));
                    
                    if(SYS_DS_LPORT_ADD != p_target->lport_list[lport_idx].upt_flag)
                    {
                        /*set IN_USE*/
                        p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag = SYS_CHAN_LPORT_OCCUPY_IN_USE;
                        tmp_lport = p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].lport;
                        p_lport_arrange[tmp_lport].using_stat = SYS_RESOURCE_IN_USE;
                    }
                }
            }
            break;
    }
    return CTC_E_NONE;
}





int32
_sys_tmm_ds_soft_table_upt(uint8 lchip, sys_tmm_ds_target_attr_t* p_target)
{
    uint8  idx;
    uint8  i;
    uint8  find_flag = FALSE;
    uint8  dst_mode;
    uint8  dst_lport_idx;
    uint8  logic_serdes_id;
    uint8  hss_id           = 0;
    uint8  inner_lane_id    = 0;
    uint8  lane_num_new     = 0;
    uint8  port_num_new     = 0;
    uint8  is_lport_drop    = TRUE;    
    sys_datapath_hss_attribute_t* p_hss_vec = NULL;
    sys_datapath_serdes_info_t*   p_serdes  = NULL;
    
    /*1. update serdes info*/
    for(idx = 0; idx < p_target->serdes_num; idx++)
    {
        is_lport_drop   = TRUE;
        logic_serdes_id = p_target->serdes_list[idx].logic_serdes_id;
        dst_mode        = p_target->serdes_list[idx].dst_mode;
        hss_id          = SYS_TMM_MAP_SERDES_TO_HSS_IDX(logic_serdes_id);
        p_hss_vec = ctc_vector_get(p_usw_datapath_master[lchip]->p_hss_vector, hss_id);
        SYS_CONDITION_CONTINUE(p_hss_vec == NULL);
        inner_lane_id   = SYS_TMM_MAP_SERDES_TO_LANE_ID(logic_serdes_id);
        p_serdes = &(p_hss_vec->serdes_info[inner_lane_id]);

        SYS_TMM_GET_LANE_NUM_BY_MODE(dst_mode, lane_num_new);
        SYS_TMM_GET_PORT_NUM_BY_MODE(dst_mode, port_num_new);

        p_serdes->pcs_l_id = idx % lane_num_new;

        /*find related lport of this lane, and update serdes info (lport & chan) if lport is add/remain*/
        dst_lport_idx = p_target->serdes_list[idx].dst_lport_idx;
        SYS_CONDITION_CONTINUE(SYS_DATAPATH_DS_MAX_PORT_NUM <= dst_lport_idx);

        /*if this serdes is old for lport, drop it*/
        if((SYS_TMM_USELESS_ID8 != dst_lport_idx) && (SYS_DS_LPORT_DROP != p_target->lport_list[dst_lport_idx].upt_flag))
        {
            find_flag = FALSE;
            for(i = 0; i < p_target->lport_list[dst_lport_idx].serdes_relate_num; i++)
            {
                if(idx == p_target->lport_list[dst_lport_idx].serdes_relate[i].serdes_list_idx)
                {
                    find_flag = TRUE;
                    break;
                }
            }
            if(find_flag && (SYS_DS_LPORT_SERDES_NEW == p_target->lport_list[dst_lport_idx].serdes_relate[i].relate_flag))
            {
                is_lport_drop = FALSE;
            }
        }

        /*update serdes info (lport & chan): if lport is dropped, re-calculating lport & chan, else using p_ds_attr lport*/
        if(is_lport_drop)
        {
            if(0 != port_num_new)
            {
                p_serdes->lport   = p_hss_vec->serdes_info[inner_lane_id - (p_serdes->pcs_l_id)].lport;
                p_serdes->chan_id = p_hss_vec->serdes_info[inner_lane_id - (p_serdes->pcs_l_id)].chan_id;
            }
            else
            {
                p_serdes->lport   = SYS_TMM_USELESS_ID16;
                p_serdes->chan_id = SYS_TMM_USELESS_ID16;
            }
            p_serdes->pll_sel = 0;
        }
        else
        {
            p_serdes->lport   = p_target->lport_list[dst_lport_idx].lport;
            p_serdes->chan_id = p_target->lport_list[dst_lport_idx].chan_id;
            p_serdes->pll_sel = 1;
        }
        p_serdes->port_num = port_num_new;
        p_serdes->mode     = dst_mode;
        p_serdes->overclocking_speed = p_target->serdes_list[idx].ovclk_flag;
        /*overclocking_speed changed in sys_tmm_serdes_set_glb_info*/
    }

    /*2. update port attr*/
    for(idx = 0; idx < p_target->lport_num; idx++)
    {
        CTC_ERROR_RETURN(sys_tmm_datapath_port_attr_upt(lchip, p_target, idx));
    }

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_init_get_available_lport(uint8 lchip, uint16 lport_start, uint16* p_lport)
{
    uint8  arrange_type;
    uint8  find_flag = FALSE;
    uint16 idx;
    uint16 lport = SYS_TMM_USELESS_ID16;
    sys_resource_manage_item_info_t *p_lport_arrange   = p_usw_datapath_master[lchip]->resource_manage.lport_arrange;

    for(idx = 0; idx < (SYS_TMM_LPORT_NUM-lport_start); idx++)
    {
        lport = lport_start + idx;
        arrange_type = p_lport_arrange[lport].arrange_type;

        if(SYS_BMP_IS_SET(arrange_type, SYS_BMP_TO_VAL_U8(SYS_ARRANGE_MISC_CHAN_BMP)))
        {
            continue;
        }
        find_flag = TRUE;
        break;
    }
    SYS_CONDITION_RETURN(!find_flag, CTC_E_NO_RESOURCE);
    
    SYS_USW_VALID_PTR_WRITE(p_lport, lport);
    
    return CTC_E_NONE;
}

static uint8 sys_tmm_datapath_init_get_stack_en(ctc_datapath_global_cfg_t* p_cfg)
{
    uint16 serdes = 0;
    uint8 stack_enable = 1;

    for(serdes = 0; serdes < CTC_DATAPATH_SERDES_NUM; serdes++)
    {
        /* serdes flag bit0 set means stack is enabled */
        if (SYS_BMP_IS_SET(p_cfg->serdes[serdes].flag, CTC_DATAPATH_SERDES_FLAG_LPORT_VALID))
        {
            break;
        }
    }

    if (CTC_DATAPATH_SERDES_NUM == serdes)
    {
        stack_enable = 0;
    }

    return stack_enable;
}

int32
sys_tmm_datapath_init_build_lport_info(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
    uint8  hss_id           = 0;
    uint8  inner_lane_id    = 0;
    uint16 dp_chan_id       = 0;
    uint8  txqm_id          = 0;
    uint32 bandwidth        = 0;
    uint16 lport            = 0;
    uint8  dp               = 0;
    uint16  logic_serdes     = 0;
    uint8  quad_idx         = 0;
    uint16 lport_idle       = 0;
    uint8  lane_num         = 0;
    uint8  stack_en         = 0;
    uint16 max_lport        = 0;
    uint8  lport2lsd[SYS_TMM_LPORT_NUM];      /*lport to logic serdes relation, index-lport, value-logic serdes*/
    uint8  quad_flag[CTC_DATAPATH_SERDES_NUM-4] = {0};
    uint8  skip_flag[CTC_DATAPATH_SERDES_NUM-4] = {0};  /*0-no skip && no specify lport, 1-no skip && specify, 2-skip*/
    sys_datapath_hss_attribute_t* p_hss_vec     = NULL;
    sys_datapath_serdes_info_t*   p_serdes      = NULL;

    /*1. build lport - logic serdes relation*/
    /*1.1 build specified lport - serdes relation*/
    sal_memset(lport2lsd, SYS_TMM_USELESS_ID8, sizeof(lport2lsd)/sizeof(uint8));
    stack_en = sys_tmm_datapath_init_get_stack_en(p_datapath_cfg);
    for(logic_serdes = 0; logic_serdes < (CTC_DATAPATH_SERDES_NUM-4); logic_serdes++)
    {
        SYS_TMM_GET_LANE_NUM_BY_MODE(p_datapath_cfg->serdes[logic_serdes].mode, lane_num);
        if((((SYS_TMM_MAX_SERDES_NUM+SYS_TMM_CPUMAC_SERDES_NUM) <= p_datapath_cfg->serdes[logic_serdes].physical_serdes_id) && 
             (SYS_TMM_USELESS_ID8 != p_datapath_cfg->serdes[logic_serdes].physical_serdes_id)) || 
           ((TMM_SERDES_DYN_FORBID_ALL == p_datapath_cfg->serdes[logic_serdes].is_dynamic) && 
            (SYS_TMM_IS_MODE_NONE(p_datapath_cfg->serdes[logic_serdes].mode) || (0 != logic_serdes % lane_num))))
        {
            skip_flag[logic_serdes] = 2;
            continue;
        }
        
        if((CTC_CHIP_SERDES_QSGMII_MODE == p_datapath_cfg->serdes[logic_serdes].mode) || 
           (TMM_SERDES_DYN_ALLOW_ALL == p_datapath_cfg->serdes[logic_serdes].is_dynamic))
        {
            quad_flag[logic_serdes] = 1;
        }

        if((stack_en) && (p_datapath_cfg->serdes[logic_serdes].lport <= SYS_DMPS_MISC_PORT_START))
        {
            skip_flag[logic_serdes] = 1;
            lport = p_datapath_cfg->serdes[logic_serdes].lport;
            SYS_ERROR_RETURN_SET_LPORT2LSD(lport, lport2lsd[lport], logic_serdes);
            max_lport = lport > max_lport ? lport : max_lport;
            if(quad_flag[logic_serdes])
            {
                SYS_ERROR_RETURN_SET_LPORT2LSD(lport+1, lport2lsd[lport+1], logic_serdes);
                SYS_ERROR_RETURN_SET_LPORT2LSD(lport+2, lport2lsd[lport+2], logic_serdes);
                SYS_ERROR_RETURN_SET_LPORT2LSD(lport+3, lport2lsd[lport+3], logic_serdes);
                max_lport = (lport+3) > max_lport ? (lport+3) : max_lport;
            }
        }
    }

    /*1.2 build auto arranged relation*/
    for(logic_serdes = 0; logic_serdes < (CTC_DATAPATH_SERDES_NUM-4); logic_serdes++)
    {
        SYS_TMM_GET_LANE_NUM_BY_MODE(p_datapath_cfg->serdes[logic_serdes].mode, lane_num);
        SYS_CONDITION_CONTINUE((0 != skip_flag[logic_serdes]) || 
            (((SYS_TMM_MAX_SERDES_NUM+SYS_TMM_CPUMAC_SERDES_NUM) <= p_datapath_cfg->serdes[logic_serdes].physical_serdes_id) || 
            ((TMM_SERDES_DYN_FORBID_ALL == p_datapath_cfg->serdes[logic_serdes].is_dynamic) && 
             (SYS_TMM_IS_MODE_NONE(p_datapath_cfg->serdes[logic_serdes].mode) || (0 != logic_serdes % lane_num)))));

        for(; lport_idle < SYS_TMM_LPORT_NUM; lport_idle++)
        {
            SYS_CONDITION_BREAK(SYS_TMM_USELESS_ID8 == lport2lsd[lport_idle]);
        }
        if(lport_idle < (SYS_TMM_LPORT_NUM - 4))
        {
            SYS_ERROR_RETURN_SET_LPORT2LSD(lport_idle, lport2lsd[lport_idle], logic_serdes);
            max_lport = lport_idle > max_lport ? lport_idle : max_lport;
            if(quad_flag[logic_serdes])
            {
                SYS_ERROR_RETURN_SET_LPORT2LSD(lport_idle+1, lport2lsd[lport_idle+1], logic_serdes);
                SYS_ERROR_RETURN_SET_LPORT2LSD(lport_idle+2, lport2lsd[lport_idle+2], logic_serdes);
                SYS_ERROR_RETURN_SET_LPORT2LSD(lport_idle+3, lport2lsd[lport_idle+3], logic_serdes);
                max_lport = (lport_idle+3) > max_lport ? (lport_idle+3) : max_lport;
            }
        }
        else
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %d: not enough idle lport! logic_serdes %u\n", __LINE__, logic_serdes);
            return CTC_E_INVALID_PARAM;
        }
    }

    /*2. build channel-lport map*/
    lport = 0;
    for(dp = 0; dp < SYS_TMM_DP_NUM; dp++)
    {
        for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
        {
            SYS_CONDITION_CONTINUE(SYS_TMM_IS_MISC_CHAN(dp, dp_chan_id));
            SYS_CONDITION_CONTINUE(SYS_CHAN_LPORT_OCCUPY_RSV == p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp][dp_chan_id].occupy_flag);

            logic_serdes = p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp][dp_chan_id].logic_serdes_id;
            if((logic_serdes < CTC_DATAPATH_SERDES_NUM-4) && quad_flag[logic_serdes] && (0 != dp_chan_id % 4))
            {
                quad_idx++;
            }
            else
            {
                quad_idx = 0;
            }
            for(lport = 0; lport < SYS_TMM_LPORT_NUM; lport++)
            {
                if((lport < SYS_TMM_LPORT_NUM) && ((lport + quad_idx) < SYS_TMM_LPORT_NUM) && 
                   (lport2lsd[lport] == logic_serdes) && (lport2lsd[lport + quad_idx] == logic_serdes))
                {
                    lport += quad_idx;
                    break;
                }
            }

            if(lport < SYS_TMM_LPORT_NUM)
            {
                p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp][dp_chan_id].lport = lport;
            }
            else
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %d: illegal lport! %u\n", __LINE__, lport);
                return CTC_E_INVALID_PARAM;
            }

            p_usw_datapath_master[lchip]->resource_manage.dp_lport_end[dp] = (0 == dp) ? dp_chan_id : 
                p_usw_datapath_master[lchip]->resource_manage.dp_lport_end[0] + 1 + dp_chan_id;
        }
    }

    /*3. build serdes-lport info & port_attr*/
    for(hss_id = 0; hss_id < SYS_TMM_MAX_HSS_NUM; hss_id++)
    {
        p_hss_vec = ctc_vector_get(p_usw_datapath_master[lchip]->p_hss_vector, hss_id);
        SYS_CONDITION_CONTINUE(NULL == p_hss_vec);
        
        for(inner_lane_id = 0; inner_lane_id < SYS_TMM_LANE_NUM_PER_HSS; inner_lane_id++)
        {
            p_serdes = &(p_hss_vec->serdes_info[inner_lane_id]);
            SYS_CONDITION_CONTINUE(SYS_TMM_IS_MODE_NONE(p_serdes->mode));
            dp = SYS_TMM_GET_DP_ID_FROM_CHANID(p_serdes->chan_id);
            dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(p_serdes->chan_id);
            p_serdes->lport = p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp][dp_chan_id].lport;
            CTC_ERROR_RETURN(sys_tmm_datapath_build_port_attr(lchip, p_serdes));
        }
    }

    /*TXQM 01&4&5 400G BW check*/
    for(txqm_id = 0; txqm_id < SYS_TMM_TXQM_NUM_PER_DP*2; txqm_id++)
    {
        SYS_CONDITION_CONTINUE(!SYS_TMM_IS_PCS_X16(txqm_id));
        CTC_ERROR_RETURN(sys_tmm_mac_get_txqm_bandwidth(lchip, txqm_id, &bandwidth));
        if(SYS_TMM_MAX_BANDWIDTH_PER_TXQM < bandwidth)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " txqm_id %u bandwidth %u exceeds max value!\n", txqm_id, bandwidth);
            return CTC_E_NO_RESOURCE;
        }
    }

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_init_build_serdes_info(uint8 lchip, ctc_datapath_serdes_prop_t* p_serdes_raw)
{
    uint8  hss_id           = SYS_TMM_MAP_SERDES_TO_HSS_IDX(p_serdes_raw->logical_serdes_id);
    uint8  inner_lane_id    = SYS_TMM_MAP_SERDES_TO_LANE_ID(p_serdes_raw->logical_serdes_id);
    uint8  width            = 0;
    uint8  div              = 0;
    uint8  pcs_l_id         = 0;
    uint8  lane_num         = 0;
    uint8  new_chan         = 0;
    uint8  chan_num         = 0;
    uint8  need_add         = FALSE;
    uint8  need_free        = TRUE;
    uint8  serdes_mode      = p_serdes_raw->mode;
    uint16  ovclk_speed     = CTC_CHIP_SERDES_OCS_MODE_NONE;
    int32  ret              = CTC_E_NONE;
    
    sys_datapath_hss_attribute_t* p_hss_vec = NULL;
    sys_datapath_serdes_info_t*   p_serdes  = NULL;

    SYS_CONDITION_RETURN(((SYS_TMM_MAX_SERDES_NUM+SYS_TMM_CPUMAC_SERDES_NUM) <= p_serdes_raw->logical_serdes_id), CTC_E_NONE);
    if(((SYS_TMM_MAX_SERDES_NUM+SYS_TMM_CPUMAC_SERDES_NUM) <= p_serdes_raw->physical_serdes_id) && 
       (SYS_TMM_USELESS_ID8 != p_serdes_raw->physical_serdes_id))
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %% Serdes %u exceeds max value!\n", p_serdes_raw->physical_serdes_id);
        return CTC_E_INVALID_CONFIG;
    }

    p_hss_vec = ctc_vector_get(p_usw_datapath_master[lchip]->p_hss_vector, hss_id);
    if (p_hss_vec == NULL)
    {
        /*first usefull serdes in hss*/
        p_hss_vec = (sys_datapath_hss_attribute_t*)mem_malloc(MEM_SYSTEM_MODULE, sizeof(sys_datapath_hss_attribute_t));
        if(NULL == p_hss_vec)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% No memory \n");
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_hss_vec, 0, sizeof(sys_datapath_hss_attribute_t));
        need_add = TRUE;
    }
    
    /*1. fill serdes info soft table*/
    p_hss_vec->hss_id = hss_id;
    SYS_TMM_GET_HSS_TYPE(hss_id, p_hss_vec->hss_type);
    p_serdes = &(p_hss_vec->serdes_info[inner_lane_id]);
    
    p_serdes->is_dyn             = (SYS_TMM_USELESS_ID8 == p_serdes_raw->physical_serdes_id) ? 
                                   TMM_SERDES_DYN_FORBID_ALL : p_serdes_raw->is_dynamic;        //_tmm_serdes_isdyn_flag_t
    p_serdes->physical_serdes_id = (SYS_TMM_IS_MODE_NONE(p_serdes_raw->mode) && 
                                    (TMM_SERDES_DYN_FORBID_ALL == p_serdes->is_dyn)) ? 
                                   SYS_TMM_USELESS_ID8 : p_serdes_raw->physical_serdes_id;         //real serdes id
    p_serdes->rx_polarity        = p_serdes_raw->rx_polarity;       //polarity
    p_serdes->tx_polarity        = p_serdes_raw->tx_polarity;       //polarity
    p_serdes->lane_id            = inner_lane_id;                   //0~7
    p_serdes->group              = inner_lane_id;                   //0~7

    if(SYS_TMM_IS_MODE_NONE(p_serdes_raw->mode) || (SYS_TMM_USELESS_ID8 == p_serdes_raw->physical_serdes_id))
    {
        p_serdes->mode     = CTC_CHIP_SERDES_NONE_MODE;              //mode

        /*only none mode set to 0xffff. other valid modes set lport & chan in port init*/
        p_serdes->lport    = SYS_TMM_USELESS_ID16;
        p_serdes->chan_id  = SYS_TMM_USELESS_ID16;
        p_serdes->port_num = SYS_TMM_USELESS_ID8;
    }
    else
    {
        /*mapping CTC_CHIP_SERDES_XLG_R2_MODE to CTC_CHIP_SERDES_LG_MODE & CTC_CHIP_SERDES_OCS_MODE_20_625G*/
        if(CTC_CHIP_SERDES_XLG_R2_MODE == p_serdes_raw->mode)
        {
            serdes_mode = CTC_CHIP_SERDES_LG_MODE;
            ovclk_speed = CTC_CHIP_SERDES_OCS_MODE_20_625G;
        }
        else if(SYS_TMM_MODE_IS_PAM4(serdes_mode))
        {
            ovclk_speed = CTC_CHIP_SERDES_OCS_MODE_51_56G;
        }
        
        SYS_TMM_GET_LANE_NUM_BY_MODE(p_serdes_raw->mode, lane_num);

        p_serdes->pcs_l_id           = inner_lane_id % lane_num;        //0~lane_num-1
        p_serdes->mode               = serdes_mode;              //mode
        p_serdes->pll_sel            = 1;
        p_serdes->bit_width          = width;
        p_serdes->rate_div           = div;
        p_serdes->overclocking_speed = ovclk_speed; /*changed in sys_tmm_serdes_set_glb_info*/
    }

    /*2. alloc new lport*/
    CTC_ERROR_GOTO(_sys_tmm_datapath_init_chan_2_logic_serdes_map(lchip, hss_id, inner_lane_id, p_serdes->mode, 
        p_serdes->is_dyn, &new_chan, &chan_num), ret, RELEASE_PTR_RETURN);

    pcs_l_id = p_serdes->pcs_l_id;
    if(0 == pcs_l_id)
    {
        p_serdes->chan_id  = new_chan;
        p_serdes->port_num = chan_num;
    }
    else
    {
        if(0 != lane_num)
        {
            p_serdes->chan_id  = p_hss_vec->serdes_info[(inner_lane_id / lane_num) * lane_num].chan_id;
            p_serdes->port_num = p_hss_vec->serdes_info[(inner_lane_id / lane_num) * lane_num].port_num;
        }
    }

    if(need_add)
    {
        need_free = FALSE;
        (void)ctc_vector_add(p_usw_datapath_master[lchip]->p_hss_vector, hss_id, (void*)p_hss_vec);
    }

RELEASE_PTR_RETURN:
    if(need_add && need_free)
    {
        mem_free(p_hss_vec);
    }
    return ret;
}

int32
sys_tmm_datapath_get_idle_lport(uint8 lchip, uint8 arrange_type, uint16* p_lport)
{
    uint8  find_flag = FALSE;
    uint8  tmp_arrange_type;
    uint16 lport;
    sys_resource_manage_item_info_t *p_lport_arrange   = p_usw_datapath_master[lchip]->resource_manage.lport_arrange;

    for(lport = 0; lport < SYS_TMM_LPORT_NUM; lport++)
    {
        tmp_arrange_type = p_lport_arrange[lport].arrange_type;
        SYS_CONDITION_CONTINUE(!SYS_BMP_IS_SET(tmp_arrange_type, SYS_BMP_TO_VAL_U8(arrange_type)));

        if(SYS_RESOURCE_FREE == p_lport_arrange[lport].using_stat)
        {
            find_flag = TRUE;
            break;
        }
    }
    if(!find_flag)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Cannot get available lport! arrange_type %u \n", arrange_type);
        return CTC_E_NO_RESOURCE;
    }

    SYS_USW_VALID_PTR_WRITE(p_lport, lport);
    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_idle_chanid(uint8 lchip, uint8 arrange_type, uint8 dp_id, uint8* p_chan_id)
{
    uint8  find_flag = FALSE;
    uint8  tmp_arrange_type;
    uint8  chan_id;
    uint8  dp_chan_id;
    sys_resource_manage_item_info_t *p_channel_arrange = p_usw_datapath_master[lchip]->resource_manage.channel_arrange;

    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        chan_id = (uint8)(dp_chan_id + dp_id*SYS_TMM_CHANNEL_NUM_PER_DP);
        tmp_arrange_type = p_channel_arrange[chan_id].arrange_type;
        /*
        if (SYS_ARRANGE_FLEXE_PORT_BMP == arrange_type)
            printf("-- tmp_arrange_type = %d chan_id = %d\n", tmp_arrange_type, chan_id);
        */
        SYS_CONDITION_CONTINUE(!SYS_BMP_IS_SET(tmp_arrange_type, SYS_BMP_TO_VAL_U8(arrange_type)));

        if(SYS_RESOURCE_FREE == p_channel_arrange[chan_id].using_stat)
        {
            find_flag = TRUE;
            break;
        }
    }
    if(!find_flag)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Cannot get available channel! arrange_type %u, dp_id %u\n", 
            arrange_type, dp_id);
        return CTC_E_NO_RESOURCE;
    }

    SYS_USW_VALID_PTR_WRITE(p_chan_id, chan_id);
    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_idle_macid(uint8 lchip, uint8 arrange_type, uint8 txqm_id, uint16* p_mac_id)
{
    uint8  find_flag = FALSE;
    uint8  tmp_arrange_type;
    uint16 idx;
    uint16 mac_id;
    sys_resource_manage_item_info_t *p_macid_arrange   = p_usw_datapath_master[lchip]->resource_manage.macid_arrange;    
    SYS_CONDITION_RETURN(SYS_TMM_TXQM_NUM_PER_DP*2 <= txqm_id, CTC_E_INVALID_PARAM);
    for(idx = 0; idx < SYS_TMM_MAX_MAC_NUM_PER_TXQM; idx++)
    {
        mac_id = SYS_TMM_MAX_MAC_NUM_PER_TXQM*txqm_id + idx;
        tmp_arrange_type = p_macid_arrange[mac_id].arrange_type;
        SYS_CONDITION_CONTINUE(!SYS_BMP_IS_SET(tmp_arrange_type, SYS_BMP_TO_VAL_U8(arrange_type)));

        if(SYS_RESOURCE_FREE == p_macid_arrange[mac_id].using_stat)
        {
            find_flag = TRUE;
            break;
        }
    }
    if(!find_flag)
    {
        return CTC_E_NO_RESOURCE;
    }

    SYS_USW_VALID_PTR_WRITE(p_mac_id, mac_id);
    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_get_internal_chan_start(uint8 lchip, uint8 dp_id, uint16* p_chan_id)
{
    uint8  find_flag  = FALSE;
    uint16 chan_id    = 0;
    uint8  dp_chan_id = 0;
    sys_resource_manage_item_info_t *p_channel_arrange = p_usw_datapath_master[lchip]->resource_manage.channel_arrange;

    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        chan_id = dp_chan_id + dp_id*SYS_TMM_CHANNEL_NUM_PER_DP;
        if(0 == p_channel_arrange[chan_id].arrange_type)
        {
            find_flag = TRUE;
            break;
        } 
    }
    if(!find_flag)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Cannot get internal chan start! dp_id %u\n", dp_id);
        return CTC_E_NO_RESOURCE;
    }

    SYS_USW_VALID_PTR_WRITE(p_chan_id, chan_id);
    return CTC_E_NONE;
}

#define __DATAPATH__

#define __CALENDAR__

int32
_sys_tmm_dp_calculate_interval(uint8 lchip, uint32 speed, uint32 num, uint8 low_prio, uint8 extra, 
                               uint8 is_tx, uint32 bw_ratio, uint32* interval, uint32* p_cnt_sum)
{
    uint32 cnt = 0;
    uint32 avg_base = 0;
    uint32 avg_new = 0;
    uint32 cnt_org = 0;
    uint32 cnt_org_a1 = 0;
    uint32 cnt_sum = 0;
    uint32 cnt_sum_chg = 0;

    if(speed != 0)
    {
        if(is_tx)
        {
            /* division not at the end of the  expression wiil loss some accuracy */
            avg_base = bw_ratio * ((SYS_TMM_MAC_CALENDAR_BUS_WIDTH_TX*1 + 20 + 1)*8 ) * SYS_TMM_MAC_CALENDAR_CLK_MF / 
                       (2 * 1000 * speed);
        }
        else
        {
            avg_base = bw_ratio * ((SYS_TMM_MAC_CALENDAR_BUS_WIDTH_EPE+20) * 8 ) * SYS_TMM_MAC_CALENDAR_CLK_MF / 
                       (speed*1000);
        }
    }
    else
    {
        *interval = 0;
        return CTC_E_NONE;
    }

    cnt_org = avg_base / SYS_TMM_MAC_CALENDAR_MULTI_FACTOR;
    cnt_org_a1 = is_tx ? (cnt_org + 1) : cnt_org;

    if(low_prio || extra)
    {
        cnt = cnt_org_a1;
    }
    else if(num != 1)
    {
        cnt_sum = *p_cnt_sum;
        cnt_sum_chg = cnt_sum + cnt_org_a1;
        avg_new = (cnt_sum_chg * SYS_TMM_MAC_CALENDAR_MULTI_FACTOR) / num;
        cnt = (avg_new > avg_base) ? cnt_org : cnt_org_a1;
    }
    else
    {
        cnt = cnt_org;
    }

    *interval = cnt;
    *p_cnt_sum = cnt + cnt_sum;

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_sub_divisor(uint32 count, uint32 *p_speed, int16 *p_weight, int16 *weight_sum)
{
    uint16 index = 0;
    uint32 val = 0;
    uint32 max = 0;
    uint32 speed = 0;
    uint32 base = 0;
    uint32 common_div = 0;

    sal_memset(p_weight, 0, (sizeof(int16) * count));
    *weight_sum = 0;

    for(index = 0; index < count; index ++)
    {
        speed = *(p_speed + index);
        if(0 != speed)
        {
            max = speed;
            break;
        }
    }

    for(val = 1; val <= max; val ++)
    {
        common_div = 1;
        for(index = 0; index < count; index ++)
        {
            speed = *(p_speed + index);
            if(0 != (speed % val))
            {
                common_div = 0;   /*clear flag*/
                break;
            }
        }

        if(1 == common_div)
        {
            base = val;
        }
    }

    for(index = 0; index < count; index ++)
    {
        speed = *(p_speed + index);
        if((0 != speed) && (0 != base))
        {
            *(p_weight + index) = speed / base;
            *weight_sum += *(p_weight + index);
        }
    }

    return CTC_E_NONE; 
}

int32 
_sys_tmm_datapath_common_calendar(int16 entry_num, uint32 count, uint32 *p_speed, uint8 *p_error, uint16 *p_walk_end, uint16 *p_cal)
{
    uint16 mac_idx      = 0;
    int16  index        = 0;
    uint16 max_id       = 0;
    int16 weight_sum    = 0;
    int16 max_weight    = 0;
    uint8 high_prio_list[SYS_TMM_MAX_MAC_NUM_PER_DP + SYS_TMM_CPUMAC_SERDES_NUM / 2] = {0};
    uint16 en[SYS_TMM_MAX_MAC_NUM_PER_DP + SYS_TMM_CPUMAC_SERDES_NUM / 2] = {0};
    int16 *p_weight_list   = NULL;
    int16 *p_weight_list_org = NULL;

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"entry_num %u, count %u\n", entry_num, count);

    /********************************************
     * common initial phase
     ********************************************/
    p_weight_list = (int16*)mem_malloc(MEM_DMPS_MODULE, count * sizeof(int16));
    if(NULL == p_weight_list)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_weight_list, 0, count * sizeof(int16));

    for(mac_idx = 0; mac_idx < count; mac_idx ++)
    {
        en[mac_idx] = (((*(p_speed + mac_idx)) > 0) ? 1 : 0);
    }

    /* calculate divisor */
    _sys_tmm_datapath_sub_divisor(count, p_speed, p_weight_list, &weight_sum);

    *p_walk_end = weight_sum - 1;
    if(weight_sum > entry_num)
    {
        *p_error = TRUE;
        goto RELEASE_PTR_RETURN;
    }
    else
    {
        *p_error = FALSE;
    }
    
    p_weight_list_org = (int16*)mem_malloc(MEM_DMPS_MODULE, count * sizeof(int16));
    if(NULL == p_weight_list_org)
    {
        goto RELEASE_PTR_RETURN;
    }
    sal_memcpy(p_weight_list_org, p_weight_list, (sizeof(int16) * count));

    for(mac_idx = 0; mac_idx < count; mac_idx ++)
    {
        /* if weight greater than 1, then add this port into high priority list */
        high_prio_list[mac_idx] = (p_weight_list[mac_idx] > 1 ? 1 : 0);
    }
    /********************************************
     * common initial phase
     ********************************************/
    for(index = 0; index < weight_sum; index ++)
    {
        /* look up max interval */
        max_weight = 0;
        max_id = 0;

        /*1. when there is an elements in the high_prio_list greater than zero,  look up max interval in high_prio_list*/
        for(mac_idx = 0; mac_idx < count; mac_idx ++)
        {
            if(high_prio_list[mac_idx] && en[mac_idx] && (max_weight < p_weight_list[mac_idx]))
            {
                max_weight = p_weight_list[mac_idx];
                max_id = mac_idx;
            }
        }

        /*2. when all elements in the high_prio_list less than zero,  look up max interval in p_weight_list*/
        if(max_weight == 0)
        {
            for(mac_idx = 0; mac_idx < count; mac_idx ++)
            {
                if(en[mac_idx] && (max_weight < p_weight_list[mac_idx]))
                {
                    max_weight = p_weight_list[mac_idx];
                    max_id = mac_idx;
                }
            }
        }

        p_cal[index] = max_id;
        
        p_weight_list[max_id] -= weight_sum;

        for(mac_idx = 0; mac_idx < count; mac_idx ++)
        {
            if(en[mac_idx])
            {
                p_weight_list[mac_idx] += p_weight_list_org[mac_idx];
            }
        }
    }
    mem_free(p_weight_list_org);

RELEASE_PTR_RETURN:
    mem_free(p_weight_list);

    return CTC_E_NONE; 
}

int32
_sys_tmm_datapath_nettx_common_calendar(uint8 lchip, uint8 dp_id, uint8 dp_txqm_id, uint8 *p_error, 
                                                     uint16 *p_walk_end, uint16 *p_cal, sys_cal_info_collect_t* cal_info)
{
    int32  ret                  = CTC_E_NONE;
    uint8  txqm_mac_idx         = 0;
    uint16 dp_mac_id            = 0;
    int16  cal_entry_num        = 128;
    uint32 speed                = 0;
    uint32 speed_org            = 0;
    uint32 speed_2nd            = 0;
    uint32 speed_2nd_sum        = 0;
    uint32 speed_2nd_violation  = 0;
    uint32 speed_2nd_sum_max    = 0;
    uint32 *speed_list          = NULL;
    uint32 *speed_list_2nd      = NULL;

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"lchip %u, dp_id %u, dp_txqm_id %u\n", lchip, dp_id, dp_txqm_id);

    speed_list = (uint32*)mem_malloc(MEM_DMPS_MODULE, SYS_TMM_MAX_MAC_NUM_PER_TXQM * sizeof(uint32));
    if(NULL == speed_list)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(speed_list, 0, SYS_TMM_MAX_MAC_NUM_PER_TXQM * sizeof(uint32));

    speed_list_2nd = (uint32*)mem_malloc(MEM_DMPS_MODULE, SYS_TMM_MAX_MAC_NUM_PER_TXQM * sizeof(uint32));
    if(NULL == speed_list_2nd)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(speed_list_2nd, 0, SYS_TMM_MAX_MAC_NUM_PER_TXQM * sizeof(uint32));

    for(txqm_mac_idx = 0; txqm_mac_idx < SYS_TMM_MAX_MAC_NUM_PER_TXQM; txqm_mac_idx ++)
    {
        dp_mac_id = dp_txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + txqm_mac_idx;
        speed_org = cal_info[dp_mac_id].speed;

        speed = speed_org;
        speed_2nd = speed_org;

        //speed = (((speed_org > 0) && (speed_org < 1)) ? 1 : speed);
        speed_2nd = (((speed_org > 0) && (speed_org < 5)) ? 5 : speed_2nd);

        speed_list[txqm_mac_idx] = ((2 == speed) ? 25 : (speed * 10));        /* 2.5G */
        speed_list_2nd[txqm_mac_idx] = speed_2nd * 10;             /* x.5G */

        speed_2nd_sum += speed_list_2nd[txqm_mac_idx];
    }

    /* stage2 : violation detect (very important !!!!!! ) */
    speed_2nd_sum_max = 10 * SYS_TMM_MAX_BANDWIDTH_PER_TXQM * p_usw_datapath_master[lchip]->core_plla / SYS_TMM_CLK_DEFAULT;
    speed_2nd_violation = ((speed_2nd_sum > speed_2nd_sum_max) ? 1 : 0);

    /* stage3 : calculate calendar use common_calendar */
    if(speed_2nd_violation)
    {
        CTC_ERROR_GOTO(_sys_tmm_datapath_common_calendar(cal_entry_num, SYS_TMM_MAX_MAC_NUM_PER_TXQM, speed_list, 
                                                         p_error, p_walk_end, p_cal), ret, RELEASE_PTR_RETURN);
    }
    else
    {
        CTC_ERROR_GOTO(_sys_tmm_datapath_common_calendar(cal_entry_num, SYS_TMM_MAX_MAC_NUM_PER_TXQM, speed_list_2nd, 
                                                         p_error, p_walk_end, p_cal), ret, RELEASE_PTR_RETURN);
    }

    /* if TXQM is empty */
    if(0 == speed_2nd_sum)
    {
        *p_walk_end = 0;
    }
    
RELEASE_PTR_RETURN:
    mem_free(speed_list);
    mem_free(speed_list_2nd);

    return ret;
}

/*per-txqm operation*/
int32
_sys_tmm_datapath_calculate_nettx_calendar(uint8 lchip, uint8 dp_id, uint32 dp_txqm_id, 
                                                         uint16 *p_cal, uint16* walk_end, sys_cal_info_collect_t* cal_info)
{
    uint8  mactx_reorder_en[SYS_TMM_MAX_MAC_NUM_PER_TXQM]    = {0};
    uint32 interval[SYS_TMM_MAX_MAC_NUM_PER_TXQM]            = {0};/*interval,per port*/
    uint32 interval_cp[SYS_TMM_MAX_MAC_NUM_PER_TXQM+1]       = {0};/*interval,per port*/
    uint32 interval_order[SYS_TMM_MAX_MAC_NUM_PER_TXQM]      = {0};/*interval,per port*/
    uint8  active[SYS_TMM_MAX_MAC_NUM_PER_TXQM+1]            = {0};/*active list*/
    uint8  en[SYS_TMM_MAX_MAC_NUM_PER_TXQM]                  = {0};/*port enable*/
    uint8  first_cal_record_en[SYS_TMM_MAX_MAC_NUM_PER_TXQM] = {0};/*record the index first select*/
    uint32 speed_sum        = 0;
    uint32 speed            = 0;
    uint32 oversub_bw       = 300;
    uint8  oversub_flag     = FALSE;
    uint32 member_num       = 0;
    uint32  bw_ratio        = 1000;
    /*uint8  spd_2nd_flag   = FALSE;*/
    /*uint8  spd_2nd_lock   = 0;*/
    uint8  spd_max_lock     = 0;
    uint8  low_prio         = FALSE;
    uint32 cycle            = 0;  /*calendar cycle*/
    uint8  done             = FALSE;
    uint8  error            = FALSE;
    uint8  force_sel        = FALSE;
    uint32 min_id           = 1;
    uint32 min_intv         = 10000;
    uint8  min_index        = 0;
    uint8  exchange_flag    = 0;
    uint32 selport          = 0;
    uint8  extra            = FALSE;
    uint8  active_flag      = FALSE;
    uint8  illegal          = FALSE;
    uint8  reload_active    = FALSE;
    uint8  mactx_illegal    = 0;
    uint8  i                = 0; 
    uint8  k                = 0;
    uint16 dp_mac_id        = 0;
    uint32 actual_interval  = 0;
    uint32 expect_interval  = 0;
    uint32 multi_factor     = 1000;
    uint32 last_gap         = 0;
    uint32 interval_new     = 0;
    uint32 interval_sum     = 0;
    uint32 active_index_chg_dis = 0;
    uint32 intervalChk      = 0;
    uint32 intv_future      = 0;
    uint32 intv_future2     = 0;
    uint32 intv_margine     = 0;
    int32  ret = CTC_E_NONE;
    sys_nettx_cal_heap_t* p_heap = NULL;
   
    done = FALSE;
    error = FALSE;
    cycle = 0;
    speed_sum = 0;
    speed = 0;
    oversub_bw = 300;
    oversub_flag = FALSE;
    member_num = 0;
    bw_ratio = 1000;

    p_heap = (sys_nettx_cal_heap_t*)mem_malloc(MEM_DMPS_MODULE, sizeof(sys_nettx_cal_heap_t));
    CTC_ERROR_GOTO((NULL == p_heap) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_1);
    sal_memset(p_heap, 0, sizeof(sys_nettx_cal_heap_t));

    /*initial phase*/
    for(i = 0; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM; i++)
    {
        dp_mac_id = dp_txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + i;
        speed = cal_info[dp_mac_id].speed;
        speed_sum += speed;
        p_heap->first_cal_record[i] = 0;
        first_cal_record_en[i] = TRUE;
        p_heap->cnt_history[i] = 0;
    }

    if(speed_sum > oversub_bw)
    {
        oversub_flag = 1;
    }
    /*else 
    {
        bw_ratio = speed_sum * 1000 / 300;
    }*/

    /*look up low priority speed, inherit from Duet2*/
    /*spd_2nd_flag = FALSE;*/
    /*spd_2nd_lock = 0;*/
    spd_max_lock = 0;

    for(i = 0; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM; i++)
    {
        dp_mac_id = dp_txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + i;
        speed = cal_info[dp_mac_id].speed;
        if((1 <= speed) && (spd_max_lock < speed))
        {
            /*if((0 != spd_2nd_lock) && (spd_2nd_lock < spd_max_lock))
            {
                spd_2nd_flag = TRUE;
            }*/
            /*spd_2nd_lock = spd_max_lock;*/
            spd_max_lock = speed;
        }
    }
    for(i = 0; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM; i++)
    {
        dp_mac_id = dp_txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + i;
        speed = cal_info[dp_mac_id].speed;
        low_prio = oversub_flag && (spd_max_lock != speed);
        /*initial interval*/
        _sys_tmm_dp_calculate_interval(lchip, speed, 1, low_prio, 0, 1, bw_ratio, &interval_new, &(p_heap->cnt_history[i]));
        interval[i] = interval_new;
        /*initial active / enable and num*/
        if(1 <= speed)
        {
            active[i] = TRUE;
            en[i] = TRUE;
            p_heap->num[i] = 1;
            member_num++;
        }
        else  /*invalid port*/
        {
            active[i] = FALSE;
            en[i] = FALSE;
            p_heap->num[i] = 1;
            //member_num++;
        }
    }

    /*main function*/
    while((!done) && (!error))
    {
        /*reorder*/
        for(i = 1; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM+1; i++)
        {
            interval_cp[i] = interval[i-1];
        }
        /*stage1. bubble sort*/
        for(i = 1; i <= member_num; i++)
        {
            min_id = 1;
            min_intv = 10000;

            for(k = 1; k <= SYS_TMM_MAX_MAC_NUM_PER_TXQM; k++)
            {
                if((interval_cp[k]) && (min_intv > interval_cp[k]))
                {
                    min_intv = interval_cp[k];
                    min_id = k;
                }
                else if((interval_cp[k]) && (min_intv == interval_cp[k]) && active[k])
                {
                    min_id = k;
                }
            }
            interval_cp[min_id] = 10000;
            interval_order[i] = min_intv;
            p_heap->portid_order[i] = min_id - 1;
        }

        /*stage2. calendar select*/
        min_index = p_heap->portid_order[1];  /*default min interval portid*/
        min_intv = interval_order[1];  /*default min interval*/

        /*interval violation deep check if reorder the minIndex*/
        active_index_chg_dis = 0;
        for(i = 1; i <= member_num; i++)
        {
            p_heap->expect_margine[i] = 1;
        }
        for(i = 1; i <= member_num; i++)
        {
            selport = p_heap->portid_order[i];

            dp_mac_id = dp_txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + selport;
            speed = cal_info[dp_mac_id].speed;
            
            interval_sum = p_heap->cnt_history[selport];
            _sys_tmm_dp_calculate_interval(lchip, speed, p_heap->num[selport], low_prio, extra, 0, bw_ratio, &intervalChk, &interval_sum);
            intv_future = interval_order[i] - 2 + intervalChk;
            intv_future2 = interval_order[i] - 2 + intervalChk * 2 - 1;

            if ( intv_future < member_num)
            {
                for ( k = intv_future; k <= member_num; k++)
                {
                    intv_margine = interval_order[k] - k;

                    if( intv_margine <= p_heap->expect_margine[k])
                    {
                        active_index_chg_dis = 1;
                    }

                    p_heap->expect_margine[k] ++;
                }
            }
            
            /*2nd*/
            /*means selPort will be a queue-jumper after reload interval*/
            if(intv_future2 < member_num)
            {
                for ( k = intv_future2; k <= member_num; k++)
                {
                    intv_margine = interval_order[k] - k;

                    if( intv_margine <= p_heap->expect_margine[k])
                    {
                        active_index_chg_dis = 1;
                    }

                    p_heap->expect_margine[k] ++;
                }
            }
        }
        
        /*add by zed to balance mac speed port bandwidth begin*/
        force_sel = 0;
        exchange_flag = 0;
        for (i = 1; i <= member_num; i++)
        {
            selport = p_heap->portid_order[i];

            dp_mac_id = dp_txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + selport;
            speed = cal_info[dp_mac_id].speed;

            /*
             * exchange minIndex due to : 
             * 1: not the fastest speed
             * 2: doesn't set exchange_flag before
             * 3: doesn't set force_sel before
             * 4: could't exchange active index
             */
            if((speed != spd_max_lock) 
                   && (!exchange_flag)
                   && (!force_sel)
                   && (active_index_chg_dis))
            {
                min_index = p_heap->portid_order[i];
                exchange_flag = 1;
                min_intv = interval_order[i];
            }

            if(i == interval_order[i])
            {
                force_sel = 1;
            }
        }
        
        /*detect error*/
        force_sel = FALSE;
        exchange_flag = FALSE;
        for(i = 1; i <= member_num; i++)
        {
            if(i > interval_order[i])
            {
                error = 2;
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, 
                    "%% [nettx]automatic constrain failed! failed id = %u, interval = %u, cycle = %u\n", 
                    i, interval_order[i], cycle);
                for(k = 1; k <= member_num; k++)
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [nettx]bubble sort index %u, interval %u\n", 
                        k, interval_order[k]) ;
                }
                break;
            } 
            /*get the mac id*/
            selport = p_heap->portid_order[i];
            /*exchange min_index due to : 
            1: must in active list 
            2: doesn't set exchange_flag before 
            3: doesn't set force_sel before 
            4: has small interval
            5: ~activeIndexChgDis*/
            if((active[selport]) && (!exchange_flag) && (!force_sel) && (!active_index_chg_dis))
            {
                min_index = p_heap->portid_order[i];
                exchange_flag = TRUE;
                min_intv = interval_order[i];
            }
            /*force_sel eq 1 means calendar can't select the portid_order index larger than i*/
            if(i == interval_order[i])
            {
                force_sel = TRUE;
            }
        }

        /*stage3. maintain DS*/
        /*stage3.1 all interval will decrease 1*/
        for(i = 0; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM; i++)
        {
            if(en[i])   
            {
                interval[i]--;
            }
        }
        /*stage3.2 generage calendar data*/
        p_cal[cycle] = min_index;

        /*stage3.3  re-calulate interval*/
        dp_mac_id = dp_txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + min_index;
        speed = cal_info[dp_mac_id].speed;
        extra = ((1 < min_intv) && force_sel);
        low_prio = oversub_flag && (!(spd_max_lock == speed));

        _sys_tmm_dp_calculate_interval(lchip, speed, p_heap->num[min_index], low_prio, extra, 1, bw_ratio, &interval_new, &(p_heap->cnt_history[min_index]));
        interval[min_index] = interval_new;
        p_heap->num[min_index]++;  /*num++ after re-calculate interval*/
        active[min_index] = FALSE;

        /*stage3.4 record the first calendar cycle*/
        if(first_cal_record_en[min_index])
        {
            p_heap->first_cal_record[min_index] = cycle;
            first_cal_record_en[min_index] = FALSE;
        }

        /*stage4. finish calendar calculate*/
        /*4.1 detect active flag*/
        active_flag = FALSE;
        for(i = 0; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM; i++)
        {
            if(active[i])
            {
                active_flag = TRUE;
            }
        }
        /*4.2 detect interval violation*/
        /*NetTx use 1*192+1 Byte to calculate interval average*/
        if(!active_flag)
        {
            illegal = FALSE;
            mactx_illegal = 0;
            /* mactx_has_violation in net tx */
            sal_memset(mactx_reorder_en, FALSE, SYS_TMM_MAX_MAC_NUM_PER_TXQM*sizeof(uint8));
            for(i = 0; i < SYS_TMM_MAX_MAC_NUM_PER_TXQM; i++)
            {
                dp_mac_id = dp_txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + i;
                speed = cal_info[dp_mac_id].speed;
                mactx_reorder_en[i] = FALSE;
                /*port enable*/
                if(0 != speed)
                {
                    /*192*1+1 B could reach performance*/
                    expect_interval = (SYS_TMM_MAC_CALENDAR_BUS_WIDTH_TX+20+1)* SYS_TMM_MAC_CALENDAR_CLK_MF * 8 / (speed*2);
                    actual_interval = ((cycle + 1) * multi_factor) / (p_heap->num[i] - 1);
                    if(actual_interval > expect_interval)
                    {
                        illegal = TRUE;
                        active[i] = TRUE;
                    }
                    /*tail --> head gap illegal calculate*/
                    last_gap = (p_heap->first_cal_record[i] > 2) ? (p_heap->first_cal_record[i] - 2) : 0;
                    last_gap = last_gap * bw_ratio / 1000;
                    /*last_gap = first_cal_record[i];*/
                    if(last_gap > interval[i])
                    {
                        illegal = TRUE;
                        active[i] = TRUE;
                    }
                }
            }
            /*special for MacTx*/
            /*adjust calendar if interval too small*/
            /*omitted*/
            /*becasue MacTx is abandoned, mactx_illegal is not funcational*/
            reload_active = (illegal || (0 != mactx_illegal));
            /*finish if no violation*/
            if(!reload_active)
            {
                done = TRUE;
                *walk_end = cycle;
            }
        }
        cycle++;
        if(128 < cycle)
        {
            error = 1;
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [nettx]calendar cycle larger than 128, cycle %u \n", cycle);
        }
    }
    if(error)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [nettx] NetTx calendar generate mistake ! error %u\n", error);
        ret = CTC_E_INVALID_PARAM;
        goto RELEASE_PTR_RETURN_2;
    }
    
RELEASE_PTR_RETURN_2:
    mem_free(p_heap);
RELEASE_PTR_RETURN_1:
    return ret;
}

/*collecting mac id related speed and creating a temp database cal_info[], to improve calendar calculating efficiency*/
int32
sys_tmm_calendar_speed_info_collect(uint8 lchip, sys_cal_info_collect_t cal_info[], uint8 dp_id, uint8 dp_txqm_id, 
                                                uint8 cal_type)
{
    uint16 mac_id;
    uint16 lport;
    uint32 speed;
    uint16 dp_mac_id;
    uint16 txqm_mac;
    uint8  idx_dp;
    uint8  idx;
    uint8  max_txqm_num = (SYS_TMM_TXQM_NUM_PER_DP > dp_txqm_id) ? 1 : SYS_TMM_TXQM_NUM_PER_DP;
    uint8  txqm_idx;
    uint8  ovclk_speed        = 0;
    uint8  care_ovclk         = FALSE;
    uint8  is_cpumac_cal      = FALSE;
    uint8  is_mac_fix         = FALSE;
    uint8  xpipe_dual         = 0;    /*0-skip xpipe chan  1-add xpipe chan  2-skip xpipe mode=6 chan*/
    sys_datapath_lport_attr_t* port_attr = NULL;

    sal_memset(cal_info, 0, sizeof(sys_cal_info_collect_t) * (SYS_TMM_MAX_MAC_NUM_PER_DP+SYS_TMM_CPUMAC_SERDES_NUM/2));

    /*judge calendar type to get proper options, which determine how to collect speed info*/
    switch(cal_type)
    {
        case SYS_TMM_GENERAL_CAL:
            is_cpumac_cal = TRUE;
            care_ovclk    = FALSE;
            is_mac_fix    = FALSE;
            xpipe_dual = 1;
            break;
        case SYS_TMM_SKIP_XPIPE_CAL:
            is_cpumac_cal = TRUE;
            care_ovclk    = FALSE;
            is_mac_fix    = FALSE;
            xpipe_dual    = 2;
            break;
        case SYS_TMM_NETTX_CAL:
            is_cpumac_cal = FALSE;
            care_ovclk    = FALSE;
            is_mac_fix    = FALSE;
            xpipe_dual = 0;
            break;
        case SYS_TMM_MAC_CAL:
            is_cpumac_cal = FALSE;
            care_ovclk    = TRUE;
            is_mac_fix    = FALSE;
            xpipe_dual = 0;
            break;
        case SYS_TMM_MAC_FIXLEN_CAL:
            is_cpumac_cal = FALSE;
            care_ovclk    = TRUE;
            is_mac_fix    = TRUE;
            xpipe_dual = 0;
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    /*network port collect*/
    for(txqm_idx = 0; txqm_idx < max_txqm_num; txqm_idx++)
    {
        if(1 == max_txqm_num)
        {
            txqm_idx = dp_txqm_id;
        }
        for(txqm_mac = 0; txqm_mac < SYS_TMM_MAX_MAC_NUM_PER_TXQM; txqm_mac++)
        {
            dp_mac_id = txqm_idx * SYS_TMM_MAX_MAC_NUM_PER_TXQM + txqm_mac;
            mac_id    = dp_mac_id + SYS_TMM_MAX_MAC_NUM_PER_DP * dp_id;
            lport     = sys_usw_datapath_get_lport_with_mac(lchip, mac_id);
            SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == lport);

            port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
            SYS_CONDITION_CONTINUE(NULL == port_attr);
            SYS_CONDITION_CONTINUE(port_attr->port_type != SYS_DMPS_NETWORK_PORT);
            SYS_CONDITION_CONTINUE(port_attr->flexe_en);

            if(CTC_PORT_IF_FLEXE == port_attr->interface_type)
            {
                ovclk_speed = 0;
                speed = port_attr->speed_value;
            }
            else
            {
                CTC_ERROR_RETURN(sys_tmm_serdes_get_glb_info(lchip, port_attr->multi_serdes_id[0], SYS_TMM_SERDES_GLB_OVCLK_SPEED, &ovclk_speed));
                /*12.96875G per lane enlarge speed*/
                if(CTC_CHIP_SERDES_OCS_MODE_12_58G == ovclk_speed)
                {
                    speed = (CTC_CHIP_SERDES_XLG_MODE == port_attr->pcs_mode) ? 50 : 15;
                }
                else
                {
                    SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);
                }
            }

            /* use 50G speed to calculate calendar, when port is work on 40G-R2*/
            if((CTC_PORT_SPEED_40G == port_attr->speed_mode) && (CTC_PORT_IF_CR2 == port_attr->interface_type))
            {
                SYS_DATAPATH_MODE_TO_SPEED(CTC_PORT_SPEED_50G, speed);
            }

            /*use 50G speed to calculate calendar of Mac, when core frequency is 800M and port is work on 40G-R4 overclock-speeding*/
            if((800 == p_usw_datapath_master[lchip]->core_plla) && care_ovclk && (CTC_CHIP_SERDES_XLG_MODE == port_attr->pcs_mode))
            {
                if(CTC_CHIP_SERDES_OCS_MODE_NONE != ovclk_speed)
                {
                    SYS_DATAPATH_MODE_TO_SPEED(CTC_PORT_SPEED_50G, speed);
                }
            }

            if(is_mac_fix)
            {
                switch(port_attr->pcs_mode)
                {
                    case CTC_CHIP_SERDES_QSGMII_MODE:
                        speed = 5;
                        break;
                    case CTC_CHIP_SERDES_SGMII_MODE:
                        speed = 10;
                        break;
                    case CTC_CHIP_SERDES_2DOT5G_MODE:
                        /*2.5G only support in 1050M & 800M*/
                        speed = (1050 == p_usw_datapath_master[lchip]->core_plla) ? 25 : 20;
                        break;
                    default:
                        break;
                }
            }

            cal_info[dp_mac_id].cl_type = SYS_ALLOC_NORMAL;
            cal_info[dp_mac_id].chan_id = port_attr->chan_id;
            cal_info[dp_mac_id].lport   = lport;
            cal_info[dp_mac_id].speed   = speed;

            /*xpipe pmac collect*/
            SYS_CONDITION_CONTINUE(CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en);
            SYS_CONDITION_CONTINUE((0 == xpipe_dual) || ((2 == xpipe_dual) && (CTC_PORT_XPIPE_TYPE_6 == port_attr->xpipe_en)));

            cal_info[SYS_TMM_GET_MACID_PER_DP(port_attr->pmac_id)].cl_type = SYS_ALLOC_XPIPE_PMAC;
            cal_info[SYS_TMM_GET_MACID_PER_DP(port_attr->pmac_id)].chan_id = port_attr->pmac_chanid;
            cal_info[SYS_TMM_GET_MACID_PER_DP(port_attr->pmac_id)].lport   = lport;
            cal_info[SYS_TMM_GET_MACID_PER_DP(port_attr->pmac_id)].speed   = speed;
        }
    }

    /*cpumac port collect*/
    SYS_CONDITION_RETURN((!is_cpumac_cal), CTC_E_NONE);

    for(idx_dp = 0; idx_dp < SYS_TMM_CPUMAC_SERDES_NUM / 2; idx_dp++)
    {
        idx = idx_dp + (SYS_TMM_CPUMAC_SERDES_NUM / 2) * dp_id;
        mac_id = p_usw_datapath_master[lchip]->cpumac_map[idx].mac_id;
        lport = sys_usw_datapath_get_lport_with_mac(lchip, mac_id);
        SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == lport);

        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(NULL == port_attr);
        SYS_CONDITION_CONTINUE(SYS_TMM_IS_MODE_NONE(port_attr->pcs_mode));
        SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);

        idx = SYS_TMM_MAX_MAC_NUM_PER_DP + idx_dp;
        cal_info[idx].cl_type = SYS_ALLOC_NORMAL;
        cal_info[idx].chan_id = port_attr->chan_id;
        cal_info[idx].lport   = lport;
        cal_info[idx].speed   = speed;
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_calculate_general_calendar_common(uint8 lchip, uint8 dp_id, uint16* cal, uint16* walk_end, 
                                                        uint8 is_cpumac_cal, uint8* p_error, sys_cal_info_collect_t* cal_info)
{
    uint16 i, j;
    uint16 max_id = 0;
    int32  max_weight = 0;
    uint32 weight_sum = 0;
    uint8  mac_id_max = SYS_TMM_MAX_MAC_NUM_PER_DP;
    uint16 speed_list[SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)] = {0};
    int32* weight_list = NULL;
    int32* weight_list_org = NULL;
    uint8  en[SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)] = {0};
    uint16 gcd = 0;
    int32  ret = CTC_E_NONE;

    weight_list = mem_malloc(MEM_DMPS_MODULE, sizeof(int32) * (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)));
    CTC_ERROR_GOTO((NULL == weight_list) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_1);
    sal_memset(weight_list, 0, sizeof(int32) * (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)));

    weight_list_org = mem_malloc(MEM_DMPS_MODULE, sizeof(int32) * (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)));
    CTC_ERROR_GOTO((NULL == weight_list_org) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_2);
    sal_memset(weight_list_org, 0, sizeof(int32) * (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)));

    SYS_USW_VALID_PTR_WRITE(p_error, 0);

    if(is_cpumac_cal)
    {
        mac_id_max += (SYS_TMM_CPUMAC_SERDES_NUM / 2);
    }

    /*common initial phase*/
    for(i = 0; i < mac_id_max; i++)
    {
        speed_list[i] = cal_info[i].speed * 10;
        en[i] = (SYS_ALLOC_NONE_MODE == cal_info[i].cl_type) ? FALSE : TRUE;
    }
    
    /*calculate divisor*/
    CTC_ERROR_GOTO(sys_usw_datapath_get_gcd(speed_list, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)), &gcd), 
        ret, RELEASE_PTR_RETURN_3);
    for(i = 0; i < mac_id_max; i++)
    {
        weight_list[i] = speed_list[i] / gcd;
        weight_sum += weight_list[i];
        weight_list_org[i] = weight_list[i];
    }

    if(weight_sum > SYS_TMM_MAX_CAL_LEN)
    {
        SYS_USW_VALID_PTR_WRITE(p_error, 1);
        ret = CTC_E_NONE;
        goto RELEASE_PTR_RETURN_3;
    }

    /*common calendar main function*/
    for(i = 0; i < weight_sum; i++)
    {
        max_weight = 0;
        max_id = 0;

        /*stage1. look up max interval*/
        for(j = 0; j < mac_id_max; j++)
        {
            if(en[j] && (max_weight < weight_list[j]))
            {
                max_weight = weight_list[j];
                max_id = j;
            }
        }
        cal[i] = max_id;

        /*stage2. common speed list update begin*/
        weight_list[max_id] -= weight_sum;
        for(j = 0; j < mac_id_max; j++)
        {
            if(en[j])
            {
                weight_list[j] += weight_list_org[j];
            }
        }
    }

    SYS_USW_VALID_PTR_WRITE(walk_end, (weight_sum-1));
    SYS_USW_VALID_PTR_WRITE(p_error, 0);
    
RELEASE_PTR_RETURN_3:
    mem_free(weight_list_org);
RELEASE_PTR_RETURN_2:
    mem_free(weight_list);
RELEASE_PTR_RETURN_1:
    return ret;
}

/* 
 * @note        calendar indexed by mac id [ 0 ~ 159]
 */
int32
_sys_tmm_datapath_epe_netrx_common_calendar(uint8 lchip, uint8 dp_id, uint8 is_cpumac_cal, uint8 *p_error, 
                                                          uint16 *p_walk_end, uint16 *p_cal, sys_cal_info_collect_t* cal_info)
{
    int32  ret                  = CTC_E_NONE;
    uint16 cal_entry_num        = 512;
    uint16 mac_id_max           = SYS_TMM_MAX_MAC_NUM_PER_DP;
    uint32 speed                = 0;
    uint32 speed_org            = 0;
    uint32 speed_2nd            = 0;
    uint32 speed_2nd_sum        = 0;
    uint32 speed_2nd_violation  = 0;
    uint32 speed_2nd_sum_max    = 0;
    uint32 dp_mac_idx           = 0;
    uint32 *speed_list          = NULL;
    uint32 *speed_list_2nd      = NULL;

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"lchip %u, dp_id %u, is_cpumac_cal %u\n", lchip, dp_id, is_cpumac_cal);

    /********************************************
    * EpeSch common calendar 1st calculate
    ********************************************/
    /*cpumac mac id is 162 & 163 per DP, using idx 160 & 161*/
    if(is_cpumac_cal)
    {
        mac_id_max += (SYS_TMM_CPUMAC_SERDES_NUM / 2);
    }

    speed_list = (uint32*)mem_malloc(MEM_DMPS_MODULE, mac_id_max * sizeof(uint32));
    if(NULL == speed_list)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(speed_list, 0, mac_id_max * sizeof(uint32));

    speed_list_2nd = (uint32*)mem_malloc(MEM_DMPS_MODULE, mac_id_max * sizeof(uint32));
    if(NULL == speed_list_2nd)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(speed_list_2nd, 0, mac_id_max * sizeof(uint32));

    /* stage1 : init speed list */
    for(dp_mac_idx = 0; dp_mac_idx < mac_id_max; dp_mac_idx ++)
    {
        /*get port speed*/
        speed_org = cal_info[dp_mac_idx].speed;

        speed = speed_org;
        speed_2nd = speed_org;

        //speed = (((speed_org > 0) && (speed_org < 1)) ? 1 : speed);
        speed_2nd = (((speed_org > 0) && (speed_org < 5)) ? 5 : speed_2nd);

        speed_list[dp_mac_idx] = ((2 == speed) ? 25 : (speed * 10));       /* 2.5G */
        speed_list_2nd[dp_mac_idx] = speed_2nd * 10;            /* x.5G */

        speed_2nd_sum += speed_list_2nd[dp_mac_idx];
    }

    /* stage2 : violation detect (very important !!!!!! ) */
    speed_2nd_sum_max = 10 * SYS_TMM_DP_BW_MAX * p_usw_datapath_master[lchip]->core_plla / SYS_TMM_CLK_DEFAULT;
    speed_2nd_violation = ((speed_2nd_sum > speed_2nd_sum_max) ? 1 : 0);

    /* stage3 : calculate calendar use common_calendar */
    if(speed_2nd_violation)
    {
        CTC_ERROR_GOTO(_sys_tmm_datapath_common_calendar(cal_entry_num, mac_id_max, speed_list, p_error, p_walk_end, p_cal), 
            ret, RELEASE_PTR_RETURN);
    }
    else
    {
        CTC_ERROR_GOTO(_sys_tmm_datapath_common_calendar(cal_entry_num, mac_id_max, speed_list_2nd, p_error, p_walk_end, p_cal), 
            ret, RELEASE_PTR_RETURN);
    }

    /* if PP is empty */
    if(0 == speed_2nd_sum)
    {
        *p_walk_end = 0;
    }

RELEASE_PTR_RETURN:
    mem_free(speed_list);
    mem_free(speed_list_2nd);
    return ret;
}

int32
_sys_tmm_datapath_calculate_general_calendar(uint8 lchip, uint8 optimize_cal, uint8 dp_id, 
                                                uint16* cal_epe, uint16* walk_end_epe, uint8 is_cpumac_cal, 
                                                uint8* p_error, uint32 mind_depth, sys_cal_info_collect_t* cal_info)
{
    uint8 txqm_id_0 = 0;
    uint8 p = 0;

    uint8 txqm_record = 0;
    uint16 speed_f = 0;


    //uint32 cal[SYS_TMM_TXQM_NUM_PER_DP][128] = {{0}};
    /*uint8  mactx_reorder_en[SYS_TMM_MAX_MAC_NUM_PER_DP] = {0};*/
    uint8  mac_id_max = SYS_TMM_MAX_MAC_NUM_PER_DP;
    uint32* interval = NULL;/*interval,per port*/
    uint32* interval_cp = NULL;/*interval,per port*/
    uint32* interval_order = NULL;/*interval,per port*/
    uint16* portid_order = NULL;/*interval,per port*/
    uint32* num = NULL;/*select num ,per port*/
    uint8  active[SYS_TMM_MAX_MAC_NUM_PER_DP+1 + (SYS_TMM_CPUMAC_SERDES_NUM / 2)] = {0};/*active list*/
    uint8  en[SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)] = {0};/*port enable*/
    uint16* first_cal_record = NULL;/*record the index first select*/
    uint8  first_cal_record_en[SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)] = {0};/*record the index first select*/
    uint32 speed_sum = 0;
    uint32 speed = 0;
    uint32 oversub_bw = 1400;
    uint8  oversub_flag = FALSE;
    uint32 member_num = 0;
    uint32  bw_ratio = 1000;
    /*uint8  spd_2nd_flag = FALSE;*/
    uint8  spd_2nd_lock = 0;
    uint8  spd_max_lock = 0;
    uint8  low_prio = FALSE;
    uint16 cycle    = 0;  /*calendar cycle*/
    uint8  done     = FALSE;
    /*uint8  error    = FALSE;*/
    /*uint8  force_sel = FALSE;*/
    uint16 min_id = 1;
    uint32 min_intv = 10000;
    uint16 min_index = 0;
    uint8  exchange_flag = 0;
    uint32 selport = 0;
    uint8  extra = FALSE;
    uint8  active_flag = FALSE;
    uint8  illegal = FALSE;
    uint8  reload_active = FALSE;
    /*uint8  mactx_illegal = 0;*/
    uint8  i, k;
    
    uint32 actual_interval = 0;
    uint32 expect_interval = 0;
    uint32 multi_factor = 1000;
    uint32 speed_diff = 0;
    uint8 find_same_speed = FALSE;
    uint32 diff_speed_num = 0;
    uint32* speed_record = NULL;
    uint32 max_id;
    uint32 max_speed;
    uint32* speed_order = NULL;
    uint8 force_sel_epe = FALSE;
    uint8 force_sel = FALSE;

    uint32 last_gap = 0;
    uint16 mac_id;
    uint16 mac_id_tmp;
    uint32* cnt_history = NULL;
    uint8 txqm_RR = 0;
    
    uint32 speed_rate = 1;
    uint32 num_rate = 1;
    uint32 op_round = 1;
    uint32 speed_1st_num = 0;
    uint32 speed_2nd_num = 0;
    uint32 speed_1st = 0;
    uint32 speed_2nd;
    uint16 ooo;
    uint32 speed_ooo;
    uint32 speed_tx;
    int32  ret = CTC_E_NONE;

    /*per-txqm operation*/
    
    done = FALSE;
    /*error = FALSE;*/
    cycle = 0;
    speed_sum = 0;
    speed = 0;
    oversub_flag = FALSE;
    member_num = 0;
    bw_ratio = 1000;

    *p_error = 0;

    /*cpumac mac id is 162 & 163 per DP, using idx 160 & 161*/
    if(is_cpumac_cal)
    {
        mac_id_max += (SYS_TMM_CPUMAC_SERDES_NUM / 2);
    }

    interval = (uint32*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_MAC_NUM_PER_DP+(SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));
    CTC_ERROR_GOTO((NULL == interval) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_1);
    sal_memset(interval, 0, (SYS_TMM_MAX_MAC_NUM_PER_DP+(SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));

    interval_cp = (uint32*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_MAC_NUM_PER_DP + 1 + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));
    CTC_ERROR_GOTO((NULL == interval_cp) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_2);
    sal_memset(interval_cp, 0, (SYS_TMM_MAX_MAC_NUM_PER_DP + 1 + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));

    interval_order = (uint32*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));
    CTC_ERROR_GOTO((NULL == interval_order) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_3);
    sal_memset(interval_order, 0, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));

    num = (uint32*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));
    CTC_ERROR_GOTO((NULL == num) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_4);
    sal_memset(num, 0, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));

    speed_order = (uint32*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));
    CTC_ERROR_GOTO((NULL == speed_order) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_5);
    sal_memset(speed_order, 0, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));

    cnt_history = (uint32*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_MAC_NUM + SYS_TMM_CPUMAC_SERDES_NUM) * sizeof(uint32));
    CTC_ERROR_GOTO((NULL == cnt_history) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_6);
    sal_memset(cnt_history, 0, (SYS_TMM_MAX_MAC_NUM + SYS_TMM_CPUMAC_SERDES_NUM) * sizeof(uint32));

    speed_record = (uint32*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));
    CTC_ERROR_GOTO((NULL == speed_record) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_7);
    sal_memset(speed_record, 0, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint32));

    portid_order = (uint16*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint16));
    CTC_ERROR_GOTO((NULL == portid_order) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_8);
    sal_memset(portid_order, 0, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint16));

    first_cal_record = (uint16*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint16));
    CTC_ERROR_GOTO((NULL == first_cal_record) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_9);
    sal_memset(first_cal_record, 0, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(uint16));

    /*initial phase*/
    for(i = 0; i < mac_id_max; i++)
    {
        mac_id = i;
        SYS_CONDITION_CONTINUE(SYS_ALLOC_NONE_MODE == cal_info[mac_id].cl_type);
        speed = cal_info[mac_id].speed;
        speed_sum += speed;
        first_cal_record[i] = 0;
        first_cal_record_en[i] = TRUE;
    }

    if(speed_sum > oversub_bw)
    {
        oversub_flag = 1;
    }
    /*else
    {
        bw_ratio = speed_sum*1000 / 1400;
    }*/

    /*look up low priority speed, inherit from Duet2*/
    /*spd_2nd_flag = FALSE;*/
    spd_2nd_lock = 0;
    spd_max_lock = 0;

    for(i = 0; i < mac_id_max; i++)
    {
        mac_id = i;
        SYS_CONDITION_CONTINUE(SYS_ALLOC_NONE_MODE == cal_info[mac_id].cl_type);
        speed_f = cal_info[mac_id].speed;
        
        if((speed_f != 0) && (speed_f > spd_max_lock))
        {
            spd_2nd_lock = spd_max_lock;
            spd_max_lock = speed_f;
        }

        if((speed_f != 0) && (speed_f > spd_2nd_lock) && (speed_f < spd_max_lock))
        {
            spd_2nd_lock = speed_f;
        }
    }

    /*look up different speed. for calendar optimization*/
    for(i = 0; i < mac_id_max; i++)
    {
        mac_id = i;
        SYS_CONDITION_CONTINUE(SYS_ALLOC_NONE_MODE == cal_info[mac_id].cl_type);
        speed_diff = cal_info[mac_id].speed;
        find_same_speed = FALSE;

        if(0 != speed_diff)
        {
            if(0 == diff_speed_num)
            {
                speed_record[0] = speed_diff;
                diff_speed_num++;
            }
            else
            {
                for(k = 0; k < diff_speed_num; k++)
                {
                    if(speed_record[k] == speed_diff)
                    {
                        find_same_speed = TRUE;
                    }
                }
                if(!find_same_speed)
                {
                    speed_record[diff_speed_num] = speed_diff;
                    diff_speed_num++;
                }
            }
        }
    }
    /*EPE speed array bubble sort begin*/
    for(k = 0; k < diff_speed_num; k++)
    {
        max_id = 1;
        max_speed = 0;
        for(i = 0; i < mac_id_max; i++)
        {
            if(max_speed < speed_record[i])
            {
                max_speed = speed_record[i];
                max_id = i;
            }
        }
        speed_record[max_id] = 0;
        speed_order[k] = max_speed;
    }
    
    for(i = 0; i < mac_id_max; i++)
    {
        mac_id = i;
        SYS_CONDITION_CONTINUE(SYS_ALLOC_NONE_MODE == cal_info[mac_id].cl_type);
        speed = cal_info[mac_id].speed;
        
        low_prio = oversub_flag && (spd_max_lock != speed);
        /*initial interval*/
        _sys_tmm_dp_calculate_interval(lchip, speed, 1, low_prio, 0, 0, 
                                       bw_ratio, interval + i, &(cnt_history[mac_id]));
        /*initial active / enable and num*/
        if(1 <= speed)
        {
            active[i] = TRUE;
            en[i] = TRUE;
            num[i] = 1;
            member_num++;
        }
        else  /*invalid port*/
        {
            active[i] = FALSE;
            en[i] = FALSE;
            num[i] = 1;
            //member_num++;
        }
    }

    /*main function*/
    while((!done) && (!(*p_error)))
    {
        /*reorder*/
        for(i = 1; i <= mac_id_max; i++)
        {
            interval_cp[i] = interval[i-1];
        }
        /*stage1. bubble sort*/
        for(i = 1; i <= member_num; i++)
        {
            min_id = 1;
            min_intv = 10000;
            
            for(k = 1; k <= mac_id_max; k++)
            {
                if((interval_cp[k]) && (min_intv > interval_cp[k]))
                {
                    min_intv = interval_cp[k];
                    min_id = k;
                }
                else if((interval_cp[k]) && (min_intv == interval_cp[k]) && active[k])
                {
                    min_id = k;
                }
            }
            interval_cp[min_id] = 10000;
            interval_order[i] = min_intv;
            portid_order[i] = min_id - 1;
        }

        /*stage2. calendar select*/
        min_index = portid_order[1];  /*default min interval portid*/
        min_intv = interval_order[1];  /*default min interval*/
        /*detect error*/
        /*force_sel = FALSE;*/
        exchange_flag = FALSE;
        txqm_RR = (txqm_record == 3) ? 0 : txqm_record + 1;
        for(txqm_id_0 = 0; txqm_id_0 < 4; txqm_id_0++)
        {
            uint8 force_sel_txqm = 0;

            for(i = 1; i <= member_num; i++)
            {
               if(i > interval_order[i])
               {
                    *p_error = 2;
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, 
                        "%% [general]automatic constrain failed! failed id = %u, interval = %u, cycle = %u\n", i, 
                        interval_order[i], cycle);
                    for(k = 1; k <= member_num; k++)
                    {
                        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [general]bubble sort index %u, interval %u\n", 
                            k, interval_order[k]);
                    }
                    break;
                } 
                /*get the mac id*/
                selport = portid_order[i];
                /*exchange min_index due to : 
                1: must in active list 
                2: doesn't set exchange_flag before 
                3: doesn't set force_sel before 
                4: has small interval*/
                if((active[selport]) && (!exchange_flag) && (!force_sel_txqm) && ((selport / 40) == txqm_RR))
                {
                    min_index = portid_order[i];
                    exchange_flag = TRUE;
                    min_intv = interval_order[i];
                }
            /*force_sel eq 1 means calendar can't select the portid_order index larger than i*/
                if(i == interval_order[i])
                {
                    /*force_sel = TRUE;*/
                    force_sel_txqm = TRUE;
                }
            }

            txqm_RR = (txqm_RR == 3) ? 0 : txqm_RR + 1;
        }

        /*stage2.2 loop up minIndex without TXQM RR condition*/
        force_sel_epe = 0;
        for(i = 1; i <= member_num; i++)
        {
            selport = portid_order[i];
            
            /*exchange minIndex due to : */
            /*1: must in active list */
            /*2: doesn't set exchange_flag before (may be assert by step2.1 and step2.2)*/
            /*3: doesn't set force_sel before */
            /*4: has small interval*/
            if(active[selport] && (!exchange_flag) && (!force_sel_epe))  /*epe calendar chg flag*/
            {
                min_index = portid_order[i];
                exchange_flag = TRUE;
                min_intv = interval_order[i];
            }
            /*if $force_sel_epe eq 1 ,means calendar can't select the portid_order index larger than i */
            if(i == interval_order[i])
            {
                force_sel = TRUE;
                force_sel_epe = TRUE; /*epe calendar chg flag*/
            }
        }

        /*stage3. maintain DS*/
        txqm_record = min_index / 40;
        /*stage3.1 all interval will decrease 1*/
        for(i = 0; i < mac_id_max; i++)
        {
            if(en[i])
            {
                interval[i]--;
            }
        }
        /*stage3.2 generage calendar data*/
        //cal[j][cycle] = min_index;
        cal_epe[cycle] = min_index;

        /*stage3.3  re-calulate interval*/
        mac_id = min_index;
        SYS_CONDITION_CONTINUE(SYS_ALLOC_NONE_MODE == cal_info[mac_id].cl_type);
        speed = cal_info[mac_id].speed;
        extra = (min_intv > 1) && force_sel;

        low_prio = oversub_flag && (spd_max_lock != speed);
        _sys_tmm_dp_calculate_interval(lchip, speed, num[min_index], low_prio, extra, 0, 
                                       bw_ratio, interval + min_index, &(cnt_history[mac_id]));
        num[min_index]++;  /*num++ after re-calculate interval*/
        active[min_index] = FALSE;

        /*stage3.4 record the first calendar cycle*/
        if(first_cal_record_en[min_index])
        {
            first_cal_record[min_index] = cycle;
            first_cal_record_en[min_index] = FALSE;
        }

        /*stage4. finish calendar calculate*/
        /*4.1 detect active flag*/
        active_flag = FALSE;
        
        for(i = 0; i < mac_id_max; i++)
        {
            if(active[i])
            {
                active_flag = TRUE;
            }
        }
        /*4.2 detect interval violation*/
        /*NetTx use 1*192+1 Byte to calculate interval average*/
        if(!active_flag)
        {
            /*uint8 high_speed_num = 0;
            uint8 low_speed_num = 0;*/
                
            illegal = FALSE;
            /*mactx_illegal = 0;*/
            /*sal_memset(mactx_reorder_en, FALSE, SYS_TMM_MAX_MAC_NUM_PER_DP*sizeof(uint8));*/
            for(i = 0; i < mac_id_max; i++)
            {
                mac_id = i;
                SYS_CONDITION_CONTINUE(SYS_ALLOC_NONE_MODE == cal_info[mac_id].cl_type);
                speed_tx = cal_info[mac_id].speed;

                /*if(speed_tx == spd_max_lock)
                    high_speed_num = num[i] - 1;
                if(speed_tx == spd_2nd_lock)
                    low_speed_num = num[i] - 1;*/

                /*port enable*/
                if(0 != speed_tx)
                {
                    /*192*1+1 B could reach performance*/
                    expect_interval = ((SYS_TMM_MAC_CALENDAR_BUS_WIDTH_EPE+20) * SYS_TMM_MAC_CALENDAR_CLK_MF * 8) / speed_tx;
                    actual_interval = (((uint32)cycle + 1) * multi_factor) / (num[i] - 1);
                    if(actual_interval > expect_interval)
                    {
                        illegal = TRUE;
                        active[i] = TRUE;
                    }
                    /*tail --> head gap illegal calculate*/
                    /*last_gap = first_cal_record[i];*/
                    last_gap = (first_cal_record[i] > 1) ? (first_cal_record[i] - 1) : 0;
                    last_gap = last_gap * bw_ratio / multi_factor;
                    if(last_gap > interval[i])
                    {
                        /*illegal = TRUE;
                        active[i] = TRUE;*/
                    }
                }
            }

            if(optimize_cal)
            {
                speed_rate = 1;
                num_rate = 1;
                op_round = 1;
                speed_1st_num = 0;
                speed_2nd_num = 0;

                if(1 < diff_speed_num)
                {
                    uint32 loop_cycle_max = (mind_depth > diff_speed_num) ? diff_speed_num : mind_depth;

                    for(op_round = 0; op_round <= loop_cycle_max-2; op_round++)
                    {
                        if(op_round == 0)
                        {
                            speed_1st = speed_order[op_round];
                        }
                        speed_2nd = speed_order[op_round+1];

                        for(ooo = 0; ooo < mac_id_max; ooo++)
                        {
                            mac_id_tmp = ooo;
                            SYS_CONDITION_CONTINUE(SYS_ALLOC_NONE_MODE == cal_info[mac_id_tmp].cl_type);
                            speed_ooo = cal_info[mac_id_tmp].speed;

                            if(speed_ooo == speed_1st)
                            {
                                speed_1st_num = num[ooo] - 1;
                            }
                            if(speed_ooo == speed_2nd)
                            {
                                speed_2nd_num = num[ooo] - 1;
                            }
                        }

                        SYS_CONDITION_CONTINUE((0 == speed_2nd) || (0 == speed_2nd_num));
                        speed_rate = 10 * speed_1st / speed_2nd;
                        num_rate = 10 * speed_1st_num / speed_2nd_num;

                        if(speed_rate > num_rate)
                        {
                            illegal = TRUE;
                            for(p = 0; p < mac_id_max; p++)
                            {
                                mac_id_tmp = p;
                                SYS_CONDITION_CONTINUE(SYS_ALLOC_NONE_MODE == cal_info[mac_id_tmp].cl_type);
                                speed_tx = cal_info[mac_id_tmp].speed;
                                if(speed_tx == speed_1st)
                                {
                                    active[p] = TRUE;
                                }
                            }
                            speed_1st = speed_2nd;
                        }
                        else if(speed_rate < num_rate)
                        {
                            illegal = TRUE;
                            for(p = 0; p < mac_id_max; p++)
                            {
                                mac_id_tmp = p;
                                SYS_CONDITION_CONTINUE(SYS_ALLOC_NONE_MODE == cal_info[mac_id_tmp].cl_type);
                                speed_tx = cal_info[mac_id_tmp].speed;
                                if(speed_tx == speed_2nd)
                                {
                                    active[p] = TRUE;
                                }
                            }
                        }
                        else
                        {
                            speed_1st = speed_2nd;
                        }
                    }
                }
            }

            reload_active = illegal;
            /*finish if no violation*/
            if(!reload_active)
            {
                done = TRUE;
                *walk_end_epe = cycle;
            }
        }
        cycle++;
        if(cycle >= SYS_TMM_MAX_CAL_LEN)
        {
            *p_error = 1;
        }
    }

    if(*p_error)
    {
        ret = CTC_E_INVALID_PARAM;
        goto RELEASE_PTR_RETURN_10;
    }
    
RELEASE_PTR_RETURN_10:
    mem_free(first_cal_record);
RELEASE_PTR_RETURN_9:
    mem_free(portid_order);
RELEASE_PTR_RETURN_8:
    mem_free(speed_record);
RELEASE_PTR_RETURN_7:
    mem_free(cnt_history);
RELEASE_PTR_RETURN_6:
    mem_free(speed_order);
RELEASE_PTR_RETURN_5:
    mem_free(num);
RELEASE_PTR_RETURN_4:
    mem_free(interval_order);
RELEASE_PTR_RETURN_3:
    mem_free(interval_cp);
RELEASE_PTR_RETURN_2:
    mem_free(interval);
RELEASE_PTR_RETURN_1:
    return ret;
}

int32
_sys_tmm_datapath_calculate_general_calendar_parser(uint8 lchip, uint8 dp_id, uint8 is_cpumac_cal, uint16* cal, 
                                                    uint16* walk_end, sys_cal_info_collect_t* cal_info)
{
    uint32 mind_depth[] = {10, 3, 3};
    uint8  optimize_cal[] = {1, 1, 0};
    uint8  idx;
    uint8  error = TRUE;

    /*1. First Use new calendar algorithms*/
    sal_memset(cal, 0, SYS_TMM_MAX_CAL_LEN * sizeof(uint16));
    *walk_end = 0;

    /*If don't calculation, then use old common calculation*/
    _sys_tmm_datapath_epe_netrx_common_calendar(lchip, dp_id, is_cpumac_cal, &error, walk_end, cal, cal_info);
    if(!error)
    {
        return CTC_E_NONE;
    }

    sal_memset(cal, 0, SYS_TMM_MAX_CAL_LEN * sizeof(uint16));
    *walk_end = 0;
    _sys_tmm_datapath_calculate_general_calendar_common(lchip, dp_id, cal, walk_end, is_cpumac_cal, &error, cal_info);
    if(!error)
    {
        return CTC_E_NONE;
    }

    /*then try 3 times at most*/
    for(idx = 0; idx < 3; idx++)
    {
        sal_memset(cal, 0, SYS_TMM_MAX_CAL_LEN * sizeof(uint16));
        *walk_end = 0;
        error = 0;
        _sys_tmm_datapath_calculate_general_calendar(lchip, optimize_cal[idx], dp_id, cal, walk_end, is_cpumac_cal, 
                                                     &error, mind_depth[idx], cal_info);
        if(!error)
        {
            return CTC_E_NONE;
        }
    }

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Calculation of general calendar (%s cpumac) error! dp_id %u\n", 
        (is_cpumac_cal ? "with" : "no"), dp_id);
    return CTC_E_INVALID_PARAM;
}

/* 
 * @note        -outDataCalEnable_f initial value is 1
 *              so is_back_cal checking is not working.
 *              this also means we will write to Calendar1Mem at the first time.
 *              -index by CHANNEL ID
 */
uint32
_sys_tmm_datapath_bufretrv_calendar_write_to_register(uint8 lchip, uint8 dp_id, const uint16* cal, uint16 walk_end)
{
    uint32 val_32 = 0;
    uint32 entry_id = 0;
    uint32 cmd = 0;
    uint16 i = 0;
    uint8 is_back_cal = 0;
    uint8 chan_id;
    uint8 dp_chan_id;
    uint16 mac_id;
    uint16 lport;
    uint32 table_out_cal = 0;
    uint32 table_buf_cal = 0;
    uint32 field_out_cal = 0;
    uint32 field_buf_cal = 0;
    BufRetrvDPBufPtrCalendar0Mem_m buf_cal;
    BufRetrvDPWrrCtl_m cal_ctl;

    entry_id = DRV_INS(dp_id, 0);
    
    cmd = DRV_IOR(BufRetrvDPWrrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));

    val_32 = GetBufRetrvDPWrrCtl(V, outDataCalEnable_f, &cal_ctl);
    is_back_cal = GetBufRetrvDPWrrCtl(V, bufPtrCalSel_f, &cal_ctl);
    if(val_32 == 0)
        is_back_cal = 0;
    else
        is_back_cal = is_back_cal ? 0 : 1;

    /* Entry */
    if(is_back_cal)
    {
        table_out_cal = BufRetrvDPOutDataCalendar1Mem_t;
        table_buf_cal = BufRetrvDPBufPtrCalendar1Mem_t;
        field_out_cal = BufRetrvDPOutDataCalendar1Mem_chanId_f;
        field_buf_cal = BufRetrvDPBufPtrCalendar1Mem_chanId_f;
    }
    else
    {
        table_out_cal = BufRetrvDPOutDataCalendar0Mem_t;
        table_buf_cal = BufRetrvDPBufPtrCalendar0Mem_t;
        field_out_cal = BufRetrvDPOutDataCalendar0Mem_chanId_f;
        field_buf_cal = BufRetrvDPBufPtrCalendar0Mem_chanId_f;
    }

    for(i = 0; i <= walk_end; i++)
    {
        /*cal 160 & 161 is cpumac id*/
        mac_id = cal[i] < SYS_TMM_MAX_MAC_NUM_PER_DP ? 
                 cal[i] + (dp_id * SYS_TMM_MAX_MAC_NUM_PER_DP) : 
                 p_usw_datapath_master[lchip]->cpumac_map[(cal[i] - SYS_TMM_MAX_MAC_NUM_PER_DP) + 
                    dp_id * (SYS_TMM_CPUMAC_SERDES_NUM/2)].mac_id;
        lport = sys_usw_datapath_get_lport_with_mac(lchip, mac_id);
        SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == lport);
        sys_tmm_datapath_get_chanid_by_lport(lchip, lport, &chan_id);
        dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(chan_id);

// bufRetrvDPOutDataCalendarMem ---
        entry_id = DRV_INS(dp_id, i);
        cmd = DRV_IOR(table_out_cal, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &buf_cal));

        val_32 = dp_chan_id;
        DRV_IOW_FIELD_NZ(lchip, table_out_cal
            , field_out_cal, &val_32, &buf_cal, dp_id, i);

        cmd = DRV_IOW(table_out_cal, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &buf_cal));
            
// bufRetrvDPBufPtrCalendarMem ---
        entry_id = DRV_INS(dp_id, i);
        cmd = DRV_IOR(table_buf_cal, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &buf_cal));

        val_32 = dp_chan_id;
        DRV_IOW_FIELD_NZ(lchip, table_buf_cal
            , field_buf_cal, &val_32, &buf_cal, dp_id, i);

        cmd = DRV_IOW(table_buf_cal, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &buf_cal));
    }

    /* WalkerEnd */
    if(is_back_cal)
    {
        val_32 = walk_end;
        DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_bufPtrCalWalkEndPtr1_f,
                &val_32, &cal_ctl, dp_id, 0);
        DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_outDataCalWalkEndPtr1_f,
                &val_32, &cal_ctl, dp_id, 0);
    }
    else
    {
        val_32 = walk_end;
        DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_bufPtrCalWalkEndPtr0_f,
                &val_32, &cal_ctl, dp_id, 0);
        DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_outDataCalWalkEndPtr0_f,
                &val_32, &cal_ctl, dp_id, 0);
    }
    entry_id = DRV_INS(dp_id, 0);
    cmd = DRV_IOW(BufRetrvDPWrrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));
    


    /* BankSel */
    cmd = DRV_IOR(BufRetrvDPWrrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));

    // WrrCtl   --------   
    val_32 = 1;
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_outDataCalEnable_f,
            &val_32, &cal_ctl, dp_id, 0);
    val_32 = 1;
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_bufPtrCalEnable_f,
            &val_32, &cal_ctl, dp_id, 0);
    val_32 = is_back_cal;
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_bufPtrCalSel_f,
            &val_32, &cal_ctl, dp_id, 0);
    val_32 = is_back_cal;
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_outDataCalSel_f,
            &val_32, &cal_ctl, dp_id, 0);   

    entry_id = DRV_INS(dp_id, 0);
    cmd = DRV_IOW(BufRetrvDPWrrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));
    
    return CTC_E_NONE;
}

uint32
_sys_tmm_datapath_netrx_calendar_write_to_register(uint8 lchip, uint8 dp_id, const uint16* cal, uint16 walk_end)
{
    uint32 val_32 = 0;
    uint32 entry_id = 0;
    uint32 cmd = 0;
    uint16 i = 0;
    uint8 is_back_cal = 0;
    uint32 table = 0;
    uint32 field = 0;
    NetRxCalendar0_m netrx_cal;
    NetRxCalCtl_m cal_ctl;

//NetRxCalCtl---
    entry_id = DRV_INS(dp_id, 0);
    
    cmd = DRV_IOR(NetRxCalCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));

    val_32 = GetNetRxCalCtl(V, cfgCalUsedEn_f, &cal_ctl);
    is_back_cal = GetNetRxCalCtl(V, cfgCalSel_f, &cal_ctl);
    if(val_32 == 0)
        is_back_cal = 0;
    else
        is_back_cal = is_back_cal ? 0 : 1;


//NetRxCalendar ---
    /* entry */
    table = (is_back_cal ? NetRxCalendar1_t : NetRxCalendar0_t);
    field = (is_back_cal ? NetRxCalendar1_port_f : NetRxCalendar0_port_f);
    for(i = 0; i <= walk_end; i++)
    {       
        entry_id = DRV_INS(dp_id, i);
        cmd = DRV_IOR(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &netrx_cal));

        val_32 = cal[i];
        DRV_IOW_FIELD_NZ(lchip, table, field,
                &val_32, &netrx_cal, dp_id, i);

        cmd = DRV_IOW(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &netrx_cal));
    }

    /* WalkerEnd */
    val_32 = walk_end;
    if(is_back_cal)
        DRV_IOW_FIELD_NZ(lchip, NetRxCalCtl_t, NetRxCalCtl_cfgCal1WalkEndPtr_f,
            &val_32, &cal_ctl, dp_id, 0);
    else
        DRV_IOW_FIELD_NZ(lchip, NetRxCalCtl_t, NetRxCalCtl_cfgCal0WalkEndPtr_f,
            &val_32, &cal_ctl, dp_id, 0);//         ---    
    entry_id = DRV_INS(dp_id, 0);
    cmd = DRV_IOW(NetRxCalCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));

    /* BankSel */
    cmd = DRV_IOR(NetRxCalCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));
    val_32 = 1;
    DRV_IOW_FIELD_NZ(lchip, NetRxCalCtl_t, NetRxCalCtl_cfgCalUsedEn_f,
            &val_32, &cal_ctl, dp_id, 0);
    val_32 = is_back_cal;
    DRV_IOW_FIELD_NZ(lchip, NetRxCalCtl_t, NetRxCalCtl_cfgCalSel_f,
            &val_32, &cal_ctl, dp_id, 0);
    cmd = DRV_IOW(NetRxCalCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));

    return CTC_E_NONE;
}

uint32
_sys_tmm_datapath_epe_calendar_write_to_register(uint8 lchip, uint8 dp_id, const uint16* cal, uint16 walk_end)
{
    uint32 val_32 = 0;
    uint32 entry_id = 0;
    uint32 cmd = 0;
    uint16 i = 0;
    uint8 is_back_cal = 0;
    uint32 table = 0;
    uint32 field = 0;
    EpeScheduleCalendar0Ram_m epe_cal;
    EpeScheduleCalCtl_m cal_ctl;


//EpeScheduleCalCtl---
    entry_id = DRV_INS(dp_id, 0);
    
    cmd = DRV_IOR(EpeScheduleCalCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));

    val_32 = GetEpeScheduleCalCtl(V, cfgCalUsedEn_f, &cal_ctl);
    is_back_cal = GetEpeScheduleCalCtl(V, cfgCalSelPtr_f, &cal_ctl);
    if(val_32 == 0)
        is_back_cal = 0;
    else 
        is_back_cal = is_back_cal ? 0 : 1;

//EpeScheduleCalendar[0 1]Ram ---
    /* Entry */
    table = (is_back_cal ? EpeScheduleCalendar1Ram_t : EpeScheduleCalendar0Ram_t);
    field = (is_back_cal ? EpeScheduleCalendar1Ram_calPtr_f : EpeScheduleCalendar0Ram_calPtr_f);
    for(i = 0; i <= walk_end; i++)
    {       
        entry_id = DRV_INS(dp_id, i);

        cmd = DRV_IOR(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &epe_cal));

        /*cal 160 & 161 is cpumac, which mac id is 162 & 163*/
        val_32 = (cal[i] >= SYS_TMM_MAX_MAC_NUM_PER_DP) ? (cal[i]+2) : cal[i];
        DRV_IOW_FIELD_NZ(lchip, table, field,
                    &val_32, &epe_cal, dp_id, i);

        cmd = DRV_IOW(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &epe_cal));
    }

    /* WalkerEnd */
    val_32 = walk_end;
    if(is_back_cal)
    {
        DRV_IOW_FIELD_NZ(lchip, EpeScheduleCalCtl_t, EpeScheduleCalCtl_cfgCal1WalkEndPtr_f,
            &val_32, &cal_ctl, dp_id, 0);
    }
    else
    {
        DRV_IOW_FIELD_NZ(lchip, EpeScheduleCalCtl_t, EpeScheduleCalCtl_cfgCal0WalkEndPtr_f,
            &val_32, &cal_ctl, dp_id, 0);
    }
    entry_id = DRV_INS(dp_id, 0);
    cmd = DRV_IOW(EpeScheduleCalCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));

    /* BankSel */
    cmd = DRV_IOR(EpeScheduleCalCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));
    val_32 = 1;
    DRV_IOW_FIELD_NZ(lchip,EpeScheduleCalCtl_t, EpeScheduleCalCtl_cfgCalUsedEn_f,
            &val_32, &cal_ctl, dp_id, 0);
    val_32 = is_back_cal;
    DRV_IOW_FIELD_NZ(lchip,EpeScheduleCalCtl_t, EpeScheduleCalCtl_cfgCalSelPtr_f,
            &val_32, &cal_ctl, dp_id, 0);
    cmd = DRV_IOW(EpeScheduleCalCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));

    return CTC_E_NONE;
}

/*
 * @brief       Epe, NetRx, BufRetrv share one same calendar algorithm
 *
 */
int32 
_sys_tmm_datapath_set_general_calendar(uint8 lchip, uint8 dp_id)
{
    int32  ret = CTC_E_NONE;
    uint16* cal = NULL;
    uint16 walk_end = 0;
    sys_cal_info_collect_t* cal_info = NULL;

    cal = (uint16*)mem_malloc(MEM_DMPS_MODULE, SYS_TMM_MAX_CAL_LEN * sizeof(uint16));
    CTC_ERROR_GOTO((NULL == cal) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_1);
    sal_memset(cal, 0, SYS_TMM_MAX_CAL_LEN * sizeof(uint16));

    cal_info = (sys_cal_info_collect_t*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(sys_cal_info_collect_t));
    CTC_ERROR_GOTO((NULL == cal_info) ? CTC_E_NO_MEMORY : CTC_E_NONE, ret, RELEASE_PTR_RETURN_2);

    CTC_ERROR_GOTO(sys_tmm_calendar_speed_info_collect(lchip, cal_info, dp_id, SYS_TMM_TXQM_NUM_PER_DP, SYS_TMM_SKIP_XPIPE_CAL), 
        ret, RELEASE_PTR_RETURN_3);

    /*1. calendar with cpumac*/
    CTC_ERROR_GOTO(_sys_tmm_datapath_calculate_general_calendar_parser(lchip, dp_id, TRUE, cal, &walk_end, cal_info), 
        ret, RELEASE_PTR_RETURN_3);

    if(SYS_TMM_MAX_CAL_LEN > walk_end)
    {
        /*1.1 EPE consider cpumac*/
        CTC_ERROR_GOTO(_sys_tmm_datapath_epe_calendar_write_to_register(lchip, dp_id, cal, walk_end), 
            ret, RELEASE_PTR_RETURN_3);

        /*1.2 BR consider cpumac*/
        CTC_ERROR_GOTO(_sys_tmm_datapath_bufretrv_calendar_write_to_register(lchip, dp_id, cal, walk_end), 
            ret, RELEASE_PTR_RETURN_3);
    }

    /*2. calendar without cpumac*/
    CTC_ERROR_GOTO(sys_tmm_calendar_speed_info_collect(lchip, cal_info, dp_id, SYS_TMM_TXQM_NUM_PER_DP, SYS_TMM_GENERAL_CAL), 
            ret, RELEASE_PTR_RETURN_3);

    CTC_ERROR_GOTO(_sys_tmm_datapath_calculate_general_calendar_parser(lchip, dp_id, FALSE, cal, &walk_end, cal_info), 
        ret, RELEASE_PTR_RETURN_3);

    if(SYS_TMM_MAX_CAL_LEN > walk_end)
    {
        /*2.1 NetRx no cpumac*/
        CTC_ERROR_GOTO(_sys_tmm_datapath_netrx_calendar_write_to_register(lchip, dp_id, cal, walk_end), 
            ret, RELEASE_PTR_RETURN_3);
    }
    
RELEASE_PTR_RETURN_3:
    mem_free(cal_info);
RELEASE_PTR_RETURN_2:
    mem_free(cal);
RELEASE_PTR_RETURN_1:
    return ret;
}

uint32
_sys_tmm_datapath_nettx_calendar_write_to_register(uint8 lchip, uint8 dp_id, uint32 dp_txqm_id, uint16* p_cal, uint16 walk_end)
{
    uint8  i           = 0;
    uint32 val_32      = 0;
    uint32 cmd         = 0;
    uint32 entry_id    = 0;
    uint32 is_back_cal = 0;
    uint32 table       = 0;
    uint32 field       = 0;
    uint32 step        = 0;
    NetTxCal_m     nettx_cal;
    NetTxCalCtl_m  cal_ctl;
    NetTxMiscCtl_m misc_ctl;

    entry_id = DRV_INS(dp_id, 0);
    cmd      = DRV_IOR(NetTxMiscCtl_t,  DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &misc_ctl));
    val_32   = GetNetTxMiscCtl(V, netTxReady_f, &misc_ctl);
    cmd      = DRV_IOR(NetTxCalCtl_t,  DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));
    step     = NetTxCalCtl_calEntry1Sel_f - NetTxCalCtl_calEntry0Sel_f;
    DRV_IOR_FIELD(lchip, NetTxCalCtl_t, (NetTxCalCtl_calEntry0Sel_f+step*dp_txqm_id), &is_back_cal, &cal_ctl);
    
    if(0 == val_32)
    {
        is_back_cal = 0;
    }
    else
    {
        is_back_cal = is_back_cal ? 0 : 1;
    }

    /* NetTxCal/NetTxCalBak-- txqm 0: 0~127 ; txqm 1: 128_255; ... */
    /* entry */ 
    table = is_back_cal ? NetTxCalBak_t : NetTxCal_t;
    field = is_back_cal ? NetTxCalBak_calEntry_f : NetTxCal_calEntry_f;

    for(i = 0; i <= walk_end; i++)    
    {       
        entry_id = DRV_INS(dp_id, dp_txqm_id*128+i);
        cmd      = DRV_IOR(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &nettx_cal));

        val_32   = p_cal[i];
        DRV_IOW_FIELD_NZ(lchip, table,  field, &val_32, &nettx_cal, dp_id, dp_txqm_id*128+i);

        cmd      = DRV_IOW(table, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &nettx_cal));
    }

    /* WalkerEnd */
    entry_id = DRV_INS(dp_id, 0);
    cmd      = DRV_IOR(NetTxCalCtl_t,  DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));
    if(is_back_cal)
    {
        step  = NetTxCalCtl_walkerEnd1Bak_f - NetTxCalCtl_walkerEnd0Bak_f;
        field = NetTxCalCtl_walkerEnd0Bak_f + step*dp_txqm_id;
    }
    else
    {
        step  = NetTxCalCtl_walkerEnd1_f - NetTxCalCtl_walkerEnd0_f;
        field = NetTxCalCtl_walkerEnd0_f + step*dp_txqm_id;
    }    
    val_32   = walk_end;
    DRV_IOW_FIELD_NZ(lchip, NetTxCalCtl_t,  field, &val_32, &cal_ctl, dp_id, 0);
    
    cmd      = DRV_IOW(NetTxCalCtl_t,  DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));

    /* bank sel */
    entry_id = DRV_INS(dp_id, 0);
    cmd      = DRV_IOR(NetTxCalCtl_t,  DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));

    val_32   = is_back_cal;
    step     = NetTxCalCtl_calEntry1Sel_f - NetTxCalCtl_calEntry0Sel_f;
    DRV_IOW_FIELD_NZ(lchip, NetTxCalCtl_t,  (NetTxCalCtl_calEntry0Sel_f+step*dp_txqm_id), &val_32, &cal_ctl, dp_id, 0);
    cmd      = DRV_IOW(NetTxCalCtl_t,  DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &cal_ctl));

    return CTC_E_NONE;
}

/*collecting aps info, per txqm*/
int32
sys_tmm_calendar_aps_info_collect(uint8 lchip, uint8 dp_id, uint8 dp_txqm_id, sys_aps_info_collect_t *aps_info, uint8 *need_reorder)
{
    uint16 mac_id                    = 0;
    uint16 lport                     = 0;
    uint16 dp_mac_id                 = 0;
    uint16 txqm_mac                  = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
        
    for(txqm_mac = 0; txqm_mac < SYS_TMM_MAX_MAC_NUM_PER_TXQM; txqm_mac++)
    {
        dp_mac_id = dp_txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + txqm_mac;
        mac_id    = dp_mac_id + SYS_TMM_MAX_MAC_NUM_PER_DP * dp_id;
        lport     = sys_usw_datapath_get_lport_with_mac(lchip, mac_id);
        SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == lport);

        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(NULL == port_attr);
        SYS_CONDITION_CONTINUE(port_attr->port_type != SYS_DMPS_NETWORK_PORT);
        if ((2 == port_attr->client_bind_num) && (SYS_TMM_USELESS_ID16 != port_attr->mac_id_aps))
        {
            aps_info[port_attr->mac_id % SYS_TMM_MAX_MAC_NUM_PER_TXQM].aps_type = APS_TYEE_MASTER;
            aps_info[port_attr->mac_id % SYS_TMM_MAX_MAC_NUM_PER_TXQM].brother_mac_id = port_attr->mac_id_aps % SYS_TMM_MAX_MAC_NUM_PER_TXQM;

            aps_info[port_attr->mac_id_aps % SYS_TMM_MAX_MAC_NUM_PER_TXQM].aps_type = APS_TYEE_SLAVE;
            aps_info[port_attr->mac_id_aps % SYS_TMM_MAX_MAC_NUM_PER_TXQM].brother_mac_id = port_attr->mac_id % SYS_TMM_MAX_MAC_NUM_PER_TXQM;
            
            *need_reorder = TRUE;
        }
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_nettx_calendar_reorder(uint8 lchip, uint16 walk_end, sys_aps_info_collect_t *aps_info, uint16 *p_cal)
{
    uint8 insert_aps_flag  = FALSE;
    uint8 aps_type         = 0;
    uint16 i               = 0;
    uint16 index           = 0;
    uint16 aps_brother     = 0;
    uint16 txqm_mac_id     = 0;
    uint16 brother_index   = 0;

    if(walk_end <= 1)
    {
        return CTC_E_NONE;
    }

    /* [0, walk_end -1] */
    for(index = 0; index < walk_end; index ++)
    {
        if(insert_aps_flag)
        {
            insert_aps_flag = FALSE;
            continue;
        }

        txqm_mac_id = p_cal[index];
        aps_type = aps_info[txqm_mac_id].aps_type;
        aps_brother = aps_info[txqm_mac_id].brother_mac_id;
     
        if(APS_TYEE_MASTER == aps_type)
        {
            if(p_cal[index + 1] == aps_brother)
            {
                insert_aps_flag = TRUE;
                continue;
            }
            
            /* look up it's brother(slave) in [index + 1, walk_end] */
            for(brother_index = index + 1; brother_index <= walk_end; brother_index ++)
            {
                if(p_cal[brother_index] == aps_brother)
                {
                    break;
                }
            }

            /*[index + 1, brother_index - 1] shift to [index + 2, brother_index]*/
            for(i = brother_index; i >= index + 2 ; i --)
            {
                p_cal[i] = p_cal[i - 1];
            }

            /*insert aps_brother(slave) to index + 1*/
            p_cal[index + 1] = aps_brother;
            
            insert_aps_flag = TRUE;
        }
        else if(APS_TYEE_SLAVE == aps_type)
        {
            /* look up it's brother(master) in [index + 1, walk_end] */
            for(brother_index = index + 1; brother_index <= walk_end; brother_index ++)
            {
                if(p_cal[brother_index] == aps_brother)
                {
                    break;
                }
            }

            /*[index, brother_index - 1] shift to [index + 1, brother_index]*/
            for(i = brother_index; i >= index + 1 ; i --)
            {
                p_cal[i] = p_cal[i - 1];
            }

            /*insert aps_brother(master) to index*/
            p_cal[index] = aps_brother;
            
            insert_aps_flag = TRUE;
        }         
    }
    
    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_set_nettx_calendar(uint8 lchip, uint8 dp_id, uint32 dp_txqm_id)
{
    int32   ret          = CTC_E_NONE;
    uint8   error        = TRUE;
    uint8   need_reorder = FALSE;
    uint16  walk_end     = 0;
    uint16* cal          = NULL;
    sys_cal_info_collect_t* cal_info = NULL;
    sys_aps_info_collect_t* aps_info = NULL;

    cal_info = (sys_cal_info_collect_t*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_MAC_NUM_PER_DP + (SYS_TMM_CPUMAC_SERDES_NUM / 2)) * sizeof(sys_cal_info_collect_t));
    if(NULL == cal_info)
    {
        goto RELEASE_PTR_RETURN;
    }
    cal = (uint16*)mem_malloc(MEM_DMPS_MODULE, (SYS_TMM_MAX_CAL_LEN*2) * sizeof(uint16));
    if(NULL == cal)
    {
        goto RELEASE_PTR_RETURN;
    }
    sal_memset(cal, 0, (SYS_TMM_MAX_CAL_LEN*2) * sizeof(uint16));

    aps_info = (sys_aps_info_collect_t*)mem_malloc(MEM_DMPS_MODULE, SYS_TMM_MAX_MAC_NUM_PER_TXQM * sizeof(sys_aps_info_collect_t));
    if(NULL == aps_info)
    {
        goto RELEASE_PTR_RETURN;
    }
    sal_memset(aps_info, 0, SYS_TMM_MAX_MAC_NUM_PER_TXQM * sizeof(sys_aps_info_collect_t));

    sys_tmm_calendar_speed_info_collect(lchip, cal_info, dp_id, dp_txqm_id, SYS_TMM_NETTX_CAL);

    /*1. First Use new calendar algorithms*/
    CTC_ERROR_GOTO(_sys_tmm_datapath_nettx_common_calendar(lchip, dp_id, dp_txqm_id, &error, &walk_end, cal, cal_info), 
                   ret, RELEASE_PTR_RETURN);
    /*2. If don't calculation, then use old calendar algorithms*/
    if(error)
    {
        sal_memset(cal, 0, SYS_TMM_MAX_CAL_LEN * 2 * sizeof(uint16));
        walk_end = 0;
        CTC_ERROR_GOTO(_sys_tmm_datapath_calculate_nettx_calendar(lchip, dp_id, dp_txqm_id, cal, &walk_end, cal_info), 
                       ret, RELEASE_PTR_RETURN);
    }

    /*3. If enable aps, reorder cal list*/
    sys_tmm_calendar_aps_info_collect(lchip, dp_id, dp_txqm_id, aps_info, &need_reorder);
    if(need_reorder)
    {
        _sys_tmm_datapath_nettx_calendar_reorder(lchip, walk_end, aps_info, cal);
    }
    
    if(128 > walk_end)
    {
        CTC_ERROR_GOTO(_sys_tmm_datapath_nettx_calendar_write_to_register(lchip, dp_id, dp_txqm_id, cal, walk_end), 
                       ret, RELEASE_PTR_RETURN);
    }
    
RELEASE_PTR_RETURN:
    mem_free(cal);
    mem_free(cal_info);
    mem_free(aps_info);
    
    return ret;
}

#define __WRR__

int32
_sys_tmm_datapath_set_dp_netrx_wrr_weight(uint8 lchip, uint8 dp_id)
{
    uint8   dp_txqm_id  = 0;
    uint16  txqm_mac_id = 0;
    uint16  dp_mac_id   = 0;
    uint16  lport       = 0;
    uint16  weight      = 0;
    uint32  entry_id    = 0;
    uint32  cmd         = 0;
    uint16  divisor     = 0;
    uint32  opt_weight  = 0;
    uint32  step        = NetRxWrrWeight_cfgNetWorkWeight1_f - NetRxWrrWeight_cfgNetWorkWeight0_f;
    uint16  txqm_weight[SYS_TMM_TXQM_NUM_PER_DP][SYS_TMM_MAX_MAC_NUM_PER_TXQM] = {{0}};
    uint16  weight_arr[SYS_TMM_TXQM_NUM_PER_DP] = {0};
    NetRxWrrWeight_m       wrr_cfg;
    DsNetRxPortWeightCfg_m port_weight_cfg;
    sys_datapath_lport_attr_t* port_attr = NULL;

    /*1. fill all port weight in this dp */
    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(!port_attr || port_attr->port_type != SYS_DMPS_NETWORK_PORT);
        /*dp filter*/
        SYS_CONDITION_CONTINUE(dp_id != SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id));

        SYS_DATAPATH_SPEED_TO_WRRCFG(port_attr->speed_mode, weight);

        dp_txqm_id  = SYS_TMM_GET_TXQM_PER_DP(SYS_TMM_GET_TXQM_BY_MACID(port_attr->mac_id));
        txqm_mac_id = SYS_TMM_GET_MACID_PER_TXQM(port_attr->mac_id);
        
        txqm_weight[dp_txqm_id][txqm_mac_id] = weight;
        weight_arr[dp_txqm_id]              += weight;

        /*xpipe pmac*/
        SYS_CONDITION_CONTINUE(CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en);
        txqm_mac_id = SYS_TMM_GET_MACID_PER_TXQM(port_attr->pmac_id);
        
        txqm_weight[dp_txqm_id][txqm_mac_id] = weight;
        weight_arr[dp_txqm_id]              += weight;
    }

    /*2. set NetRxWrrWeight */
    CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(weight_arr, SYS_TMM_TXQM_NUM_PER_DP, &divisor));

    entry_id = DRV_INS(dp_id, 0);
    cmd = DRV_IOR(NetRxWrrWeight_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &wrr_cfg));
    for(dp_txqm_id = 0; dp_txqm_id < SYS_TMM_TXQM_NUM_PER_DP; dp_txqm_id++)
    {
        opt_weight = weight_arr[dp_txqm_id] / divisor;
        DRV_IOW_FIELD_NZ(lchip, NetRxWrrWeight_t, (NetRxWrrWeight_cfgNetWorkWeight0_f + step*dp_txqm_id),
                &opt_weight, &wrr_cfg, dp_id, 0);
    }
    cmd = DRV_IOW(NetRxWrrWeight_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &wrr_cfg));

    /*3. set DsNetRxPortWeightCfg*/
    for(dp_txqm_id = 0; dp_txqm_id < SYS_TMM_TXQM_NUM_PER_DP; dp_txqm_id++)
    {
        CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(txqm_weight[dp_txqm_id], SYS_TMM_MAX_MAC_NUM_PER_TXQM, &divisor));
    
        for(txqm_mac_id = 0; txqm_mac_id < SYS_TMM_MAX_MAC_NUM_PER_TXQM; txqm_mac_id++)
        {
            dp_mac_id = dp_txqm_id*SYS_TMM_MAX_MAC_NUM_PER_TXQM + txqm_mac_id;

            entry_id  = DRV_INS(dp_id, dp_mac_id);
            cmd = DRV_IOR(DsNetRxPortWeightCfg_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &port_weight_cfg));

            opt_weight = txqm_weight[dp_txqm_id][txqm_mac_id] / divisor;
            DRV_IOW_FIELD_NZ(lchip, DsNetRxPortWeightCfg_t, DsNetRxPortWeightCfg_weight_f,
                    &opt_weight, &port_weight_cfg, dp_id, dp_mac_id);

            cmd = DRV_IOW(DsNetRxPortWeightCfg_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &port_weight_cfg));
        }
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_epe_xg_lg_enable(uint8 lchip, uint8 dp_id)
{
    uint8  dp_txqm_id   = 0;
    uint16 lport        = 0;
    uint16 speed        = 0;
    uint32 cmd          = 0;
    uint32 entry_id     = 0;
    uint32 txqm_mac_id  = 0;
    uint32 xg_bitmap[8] = {0};     /* 4 txqm * (2*64b only use the first 40 b) */
    uint32 lg_bitmap[8] = {0};
    uint8  step         = EpeSchedulePortEnableCfg_cfgGroup1LSPortEn_f - EpeSchedulePortEnableCfg_cfgGroup0LSPortEn_f;
    sys_datapath_lport_attr_t* port_attr = NULL;
    EpeSchedulePortEnableCfg_m port_en_cfg;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(NULL == port_attr);
        SYS_CONDITION_CONTINUE(port_attr->port_type != SYS_DMPS_NETWORK_PORT);

        SYS_CONDITION_CONTINUE(SYS_TMM_GET_DP_ID_FROM_MACID(port_attr->mac_id) != dp_id);

        SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);

        dp_txqm_id = SYS_TMM_GET_TXQM_PER_DP(port_attr->txqm_id);
        txqm_mac_id = TXQM_INNER_MAC_ID(port_attr->mac_id);

        if(speed < 50)
        {
            CTC_BMP_SET(&xg_bitmap[dp_txqm_id*2], txqm_mac_id);
            /*notice| why need unset*/
            CTC_BMP_UNSET(&lg_bitmap[dp_txqm_id*2], txqm_mac_id);
        }
        else
        {
            CTC_BMP_UNSET(&xg_bitmap[dp_txqm_id*2], txqm_mac_id);
            /*notice| why need unset*/
            CTC_BMP_SET(&lg_bitmap[dp_txqm_id*2], txqm_mac_id);
        }
        
        /*xpipe pmac*/
        SYS_CONDITION_CONTINUE((CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en) || (CTC_PORT_XPIPE_TYPE_6 == port_attr->xpipe_en));
        txqm_mac_id = TXQM_INNER_MAC_ID(port_attr->pmac_id);

        if(speed < 50)
        {
            CTC_BMP_SET(&xg_bitmap[dp_txqm_id*2], txqm_mac_id);
            /*notice| why need unset*/
            CTC_BMP_UNSET(&lg_bitmap[dp_txqm_id*2], txqm_mac_id);
        }
        else
        {
            CTC_BMP_UNSET(&xg_bitmap[dp_txqm_id*2], txqm_mac_id);
            /*notice| why need unset*/
            CTC_BMP_SET(&lg_bitmap[dp_txqm_id*2], txqm_mac_id);
        }
    }

    entry_id = DRV_INS(dp_id, 0);
    cmd = DRV_IOR(EpeSchedulePortEnableCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &port_en_cfg));

    for(dp_txqm_id = 0; dp_txqm_id < SYS_TMM_TXQM_NUM_PER_DP; dp_txqm_id++)
    {
        DRV_IOW_FIELD_NZ(lchip, EpeSchedulePortEnableCfg_t,
            EpeSchedulePortEnableCfg_cfgGroup0LSPortEn_f+dp_txqm_id*step, &xg_bitmap[dp_txqm_id*2],
            &port_en_cfg, dp_id, 0);
        DRV_IOW_FIELD_NZ(lchip, EpeSchedulePortEnableCfg_t,
            EpeSchedulePortEnableCfg_cfgGroup0HSPortEn_f+dp_txqm_id*step, &lg_bitmap[dp_txqm_id*2], 
            &port_en_cfg, dp_id, 0);
    }

    cmd = DRV_IOW(EpeSchedulePortEnableCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &port_en_cfg));

    DP_DEBUG_FUNCTION_RETURN_PRINT();
        

    return CTC_E_NONE;
}


int32
_sys_tmm_datapath_set_qmgr_xg_lg_enable(uint8 lchip, uint8 dp_id)
{
    uint32  cmd          = 0;
    uint32  xg_bitmap[4] = {0}; // 128 bit per dp
    uint32  lg_bitmap[4] = {0};        
    uint16  lport        = 0;
    uint16  speed        = 0;
    uint8   dp_chan_id   = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    
#ifdef PCS_IMG
    QMgrShellChanIdCfg_m        qmgr_deq_cfg;
#else
    QMgrDeqChanIdCfg_m          qmgr_deq_cfg;
#endif
    DP_DEBUG_FUNCTION_CALLED_PRINT();

#ifdef PCS_IMG
    cmd = DRV_IOR(QMgrShellChanIdCfg_t, DRV_ENTRY_FLAG);
#else
    cmd = DRV_IOR(QMgrDeqChanIdCfg_t, DRV_ENTRY_FLAG);
#endif
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &qmgr_deq_cfg)); 

    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(!port_attr || port_attr->port_type == SYS_DMPS_RSV_PORT || port_attr->port_type == SYS_DMPS_INACTIVE_NETWORK_PORT);

        SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);

        /*dp filter*/
        SYS_CONDITION_CONTINUE(dp_id != SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id));

        dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(port_attr->chan_id);
        if(speed < 50)
        {
            CTC_BMP_SET(xg_bitmap,   dp_chan_id);
            CTC_BMP_UNSET(lg_bitmap, dp_chan_id);
        }
        else
        {
            CTC_BMP_SET(lg_bitmap,   dp_chan_id);
            CTC_BMP_UNSET(xg_bitmap, dp_chan_id);
        }

        /*xpipe pmac*/
        SYS_CONDITION_CONTINUE((CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en) || (CTC_PORT_XPIPE_TYPE_6 == port_attr->xpipe_en));
        dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(port_attr->pmac_chanid);
        if(speed < 50)
        {
            CTC_BMP_SET(xg_bitmap,   dp_chan_id);
            CTC_BMP_UNSET(lg_bitmap, dp_chan_id);
        }
        else
        {
            CTC_BMP_SET(lg_bitmap,   dp_chan_id);
            CTC_BMP_UNSET(xg_bitmap, dp_chan_id);
        }
    }

    lg_bitmap[0] = 0xffffffff;
    lg_bitmap[1] = 0xffffffff;
    lg_bitmap[2] = 0xffffffff;
    lg_bitmap[3] = 0xffffffff;

    xg_bitmap[0] = 0xffffffff;
    xg_bitmap[1] = 0xffffffff;
    xg_bitmap[2] = 0xffffffff;
    xg_bitmap[3] = 0xffffffff;

#ifdef PCS_IMG
    if(0 == dp_id)
    {
        DRV_IOW_FIELD(lchip, QMgrShellChanIdCfg_t, QMgrShellChanIdCfg_gDp_0_cfgLGChanEn_f, lg_bitmap, &qmgr_deq_cfg);
        DRV_IOW_FIELD(lchip, QMgrShellChanIdCfg_t, QMgrShellChanIdCfg_gDp_0_cfgXGChanEn_f, xg_bitmap, &qmgr_deq_cfg);
    }
    else
    {
        DRV_IOW_FIELD(lchip, QMgrShellChanIdCfg_t, QMgrShellChanIdCfg_gDp_1_cfgLGChanEn_f, lg_bitmap, &qmgr_deq_cfg);
        DRV_IOW_FIELD(lchip, QMgrShellChanIdCfg_t, QMgrShellChanIdCfg_gDp_1_cfgXGChanEn_f, xg_bitmap, &qmgr_deq_cfg);
    }

    cmd = DRV_IOW(QMgrShellChanIdCfg_t, DRV_ENTRY_FLAG);
#else
    if(0 == dp_id)
    {
        DRV_IOW_FIELD(lchip, QMgrDeqChanIdCfg_t, QMgrDeqChanIdCfg_gDp_0_cfgLGChanEn_f, lg_bitmap, &qmgr_deq_cfg);
        DRV_IOW_FIELD(lchip, QMgrDeqChanIdCfg_t, QMgrDeqChanIdCfg_gDp_0_cfgXGChanEn_f, xg_bitmap, &qmgr_deq_cfg);
    }
    else
    {
        DRV_IOW_FIELD(lchip, QMgrDeqChanIdCfg_t, QMgrDeqChanIdCfg_gDp_1_cfgLGChanEn_f, lg_bitmap, &qmgr_deq_cfg);
        DRV_IOW_FIELD(lchip, QMgrDeqChanIdCfg_t, QMgrDeqChanIdCfg_gDp_1_cfgXGChanEn_f, xg_bitmap, &qmgr_deq_cfg);
    }

    cmd = DRV_IOW(QMgrDeqChanIdCfg_t, DRV_ENTRY_FLAG);
#endif
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &qmgr_deq_cfg));

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

/* 
 * @weight_arr      arr[16]   the firset 4 row -- LS in DP0; 
 */
int32
_sys_tmm_epe_get_net_info(uint8 lchip, uint16 low_weight_sum[SYS_TMM_TXQM_NUM_PER_DP], 
                                  uint16 high_weight_sum[SYS_TMM_TXQM_NUM_PER_DP], 
                                  uint16 weight_arr[SYS_TMM_TXQM_NUM_PER_DP][SYS_TMM_MAX_MAC_NUM_PER_TXQM], uint8 dp_id)
{
    uint16 weight      = 0;
    uint16 lport       = 0;
    uint16 speed       = 0;
    uint8  txqm_mac_id = 0;
    uint8  dp_txqm_id  = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    
    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, lport, &port_attr));
        SYS_CONDITION_CONTINUE(SYS_DMPS_NETWORK_PORT != port_attr->port_type);
        
        SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);
        SYS_DATAPATH_SPEED_TO_WRRCFG(port_attr->speed_mode, weight);

        /*just process port in this dp*/
        SYS_CONDITION_CONTINUE(SYS_TMM_GET_DP_ID_FROM_MACID(port_attr->mac_id) != dp_id);
        
        dp_txqm_id = SYS_TMM_GET_TXQM_PER_DP(port_attr->txqm_id);
        txqm_mac_id = TXQM_INNER_MAC_ID(port_attr->mac_id);
        if(speed < 50)
        {
            weight_arr[dp_txqm_id][txqm_mac_id] = weight;
            low_weight_sum[dp_txqm_id]         += weight;
        }
        else
        {
            weight_arr[dp_txqm_id][txqm_mac_id] = weight;
            high_weight_sum[dp_txqm_id]        += weight;
        }

        /*xpipe pmac*/
        SYS_CONDITION_CONTINUE((CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en) || (CTC_PORT_XPIPE_TYPE_6 == port_attr->xpipe_en));
        txqm_mac_id = TXQM_INNER_MAC_ID(port_attr->pmac_id);
        if(speed < 50)
        {
            weight_arr[dp_txqm_id][txqm_mac_id] = weight;
            low_weight_sum[dp_txqm_id]         += weight;
        }
        else
        {
            weight_arr[dp_txqm_id][txqm_mac_id] = weight;
            high_weight_sum[dp_txqm_id]        += weight;
        }
    }

    return CTC_E_NONE;
}

int32 
_sys_tmm_epe_write_net_chan_weight_cfg(uint8 lchip, 
                                                   uint16 net_weights[SYS_TMM_TXQM_NUM_PER_DP][SYS_TMM_MAX_MAC_NUM_PER_TXQM], 
                                                   uint8 dp_id)
{
    uint8  dp_txqm_id;
    uint16 dp_mac_id;
    uint16 txqm_mac_id;
    uint32 tbl_id       = 0;
    uint32 index        = 0;
    uint32 cmd          = 0;
    uint32 opt_weight   = 0;
    uint32 entry_id     = 0;
    uint16 divisor      = 0;
    uint32 step         = EpeScheduleNetPortWeightConfig1Ra_t - EpeScheduleNetPortWeightConfig0Ra_t;
    EpeScheduleNetPortWeightConfig0Ra_m net_port_weight_cfg;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    for(dp_txqm_id = 0; dp_txqm_id < SYS_TMM_TXQM_NUM_PER_DP; dp_txqm_id++)
    {
        CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(net_weights[dp_txqm_id], SYS_TMM_MAX_MAC_NUM_PER_TXQM, &divisor));
        for(txqm_mac_id = 0; txqm_mac_id < SYS_TMM_MAX_MAC_NUM_PER_TXQM; txqm_mac_id++)
        {
            SYS_CONDITION_CONTINUE(0 == net_weights[dp_txqm_id][txqm_mac_id]);
            
            dp_mac_id = dp_txqm_id * SYS_TMM_MAX_MAC_NUM_PER_TXQM + txqm_mac_id;
            entry_id = dp_mac_id % 32;
            index = DRV_INS(dp_id, entry_id);

            tbl_id = EpeScheduleNetPortWeightConfig0Ra_t + (dp_mac_id/32)*step;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &net_port_weight_cfg));
 
            opt_weight = net_weights[dp_txqm_id][txqm_mac_id] / divisor;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, 
                EpeScheduleNetPortWeightConfig0Ra_cfgWeight_f, &opt_weight, &net_port_weight_cfg, 
                dp_id, entry_id);
            
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &net_port_weight_cfg));
        }
    }
    
    DP_DEBUG_FUNCTION_RETURN_PRINT();
        
    return CTC_E_NONE;
}

int32 
_sys_tmm_epe_write_misc_chan_weight_cfg(uint8 lchip, uint8 dp_id)
{
    uint32 cmd        = 0;
    uint32 opt_weight = 0;
    uint32 entry_id   = 0;
    uint16 divisor    = 0;
    uint8  idx        = 0;
    uint8  step = EpeScheduleMiscChanWeightConfig_toCpuMac1WtCfg_f - EpeScheduleMiscChanWeightConfig_toCpuMac0WtCfg_f;
    EpeScheduleMiscChanWeightConfig_m misc_chan_weight_cfg;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(g_misc_wrr_weight, MISC_CHAN_ITEM_BUTT-2, &divisor)); 
    cmd = DRV_IOR(EpeScheduleMiscChanWeightConfig_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &misc_chan_weight_cfg));
    
    for(idx = 0; idx < MISC_CHAN_ITEM_BUTT-2; idx++)
    {
        entry_id = DRV_INS(dp_id, 0);
        
        opt_weight = g_misc_wrr_weight[idx] / divisor;
        DRV_IOW_FIELD_NZ(lchip, EpeScheduleMiscChanWeightConfig_t,
            EpeScheduleMiscChanWeightConfig_toCpuMac0WtCfg_f+idx*step, &opt_weight, &misc_chan_weight_cfg,
            dp_id, 0);
    }
    
    cmd = DRV_IOW(EpeScheduleMiscChanWeightConfig_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &misc_chan_weight_cfg));

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

/*
 * @brief       write to table EpeScheduleWrrWeightConfig
 *              
 */
int32
_sys_tmm_epe_write_wrr_weight_cfg(uint8 lchip, uint16 low_weight_sum[SYS_TMM_TXQM_NUM_PER_DP], 
                                             uint16 high_weight_sum[SYS_TMM_TXQM_NUM_PER_DP], uint8 dp)
{
    uint8  idx;
    uint8  dp_txqm_id;
    uint8  step           = 0;
    uint16 divisor_hl     = 0;
    uint16 divisor        = 0;
    uint32 opt_weight     = 0;
    uint32 entry_id       = 0;
    uint32 cmd            = 0;
    uint16 group7[2]      = {0};    //index: [0 or 1, network or misc port]
    uint16 high_low[SYS_TMM_TXQM_NUM_PER_DP][2] = {{0}};  //index: [dp_txqm_id][0 or 1, high weight sum or low weight sum]
    uint16 txqm_weight[SYS_TMM_TXQM_NUM_PER_DP] = {0};    //high + low in every txqm    index: [dp_txqm_id]
    EpeScheduleWrrWeightConfig_m wrr_cfg;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    /*info collection*/
    for(dp_txqm_id = 0; dp_txqm_id < SYS_TMM_TXQM_NUM_PER_DP; dp_txqm_id++)
    {
        high_low[dp_txqm_id][0] = high_weight_sum[dp_txqm_id];
        high_low[dp_txqm_id][1] = low_weight_sum[dp_txqm_id];
        txqm_weight[dp_txqm_id] = high_weight_sum[dp_txqm_id] + low_weight_sum[dp_txqm_id];
        group7[0] += txqm_weight[dp_txqm_id];
    }
    CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(txqm_weight, SYS_TMM_TXQM_NUM_PER_DP, &divisor));

    entry_id = DRV_INS(dp, 0);
    cmd = DRV_IOR(EpeScheduleWrrWeightConfig_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &wrr_cfg));

    /*network port*/
    for(dp_txqm_id = 0; dp_txqm_id < SYS_TMM_TXQM_NUM_PER_DP; dp_txqm_id++)
    {        
        /*LS & HS*/
        CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(high_low[dp_txqm_id], 2, &divisor_hl));
        
        step = EpeScheduleWrrWeightConfig_toGroup1LsWtCfg_f - EpeScheduleWrrWeightConfig_toGroup0LsWtCfg_f;
        opt_weight = low_weight_sum[dp_txqm_id] / divisor_hl;
        
        DRV_IOW_FIELD_NZ(lchip, EpeScheduleWrrWeightConfig_t, 
            (EpeScheduleWrrWeightConfig_toGroup0LsWtCfg_f+dp_txqm_id*step), 
            &opt_weight, &wrr_cfg, dp, 0);
        opt_weight = high_weight_sum[dp_txqm_id] / divisor_hl;
        DRV_IOW_FIELD_NZ(lchip, EpeScheduleWrrWeightConfig_t, 
            (EpeScheduleWrrWeightConfig_toGroup0HsWtCfg_f+dp_txqm_id*step), 
            &opt_weight, &wrr_cfg, dp, 0);

        /*general*/
        step = EpeScheduleWrrWeightConfig_cfgGroup5Txqm1WtCfg_f - EpeScheduleWrrWeightConfig_cfgGroup5Txqm0WtCfg_f;
        opt_weight = txqm_weight[dp_txqm_id] / divisor;
        
        DRV_IOW_FIELD_NZ(lchip, EpeScheduleWrrWeightConfig_t, 
            (EpeScheduleWrrWeightConfig_cfgGroup5Txqm0WtCfg_f+dp_txqm_id*step), &opt_weight, 
            &wrr_cfg, dp, 0);
    }

    /* GROUP 7: net vs misc */
    for(idx = 0; idx < MISC_CHAN_ITEM_BUTT-2; idx++)
    {
        group7[1] += g_misc_wrr_weight[idx];
    }
    group7[1] *= 10;
    CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(group7, 2, &divisor));
    opt_weight = group7[0] / divisor;
    DRV_IOW_FIELD_NZ(lchip, EpeScheduleWrrWeightConfig_t, 
        EpeScheduleWrrWeightConfig_cfgGroup7NetWtCfg_f,
        &opt_weight, &wrr_cfg, dp, 0);
    opt_weight = group7[1] / divisor;
    DRV_IOW_FIELD_NZ(lchip, EpeScheduleWrrWeightConfig_t, 
        EpeScheduleWrrWeightConfig_cfgGroup7MiscWtCfg_f,
        &opt_weight, &wrr_cfg, dp, 0);

    cmd = DRV_IOW(EpeScheduleWrrWeightConfig_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &wrr_cfg));

    DP_DEBUG_FUNCTION_RETURN_PRINT();
        

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_set_epe_wrr_weight(uint8 lchip, uint8 dp_id)
{
    uint16  low_weight_sum[SYS_TMM_TXQM_NUM_PER_DP]  = {0};   //index: dp_txqm_id 0~3
    uint16  high_weight_sum[SYS_TMM_TXQM_NUM_PER_DP] = {0};   //index: dp_txqm_id 0~3
    /*index: [dp_txqm_id 0~3][txqm_mac_id 0~39]*/
    uint16  net_weights[SYS_TMM_TXQM_NUM_PER_DP][SYS_TMM_MAX_MAC_NUM_PER_TXQM] = {{0}};

    /*get info*/
    CTC_ERROR_RETURN(_sys_tmm_epe_get_net_info(lchip, low_weight_sum, high_weight_sum, net_weights, dp_id));
    /*config network port epe weight*/
    CTC_ERROR_RETURN(_sys_tmm_epe_write_net_chan_weight_cfg(lchip, net_weights, dp_id));
    /*config misc port epe weight*/
    CTC_ERROR_RETURN(_sys_tmm_epe_write_misc_chan_weight_cfg(lchip, dp_id));
    /*config wrr ls & hs weight*/ 
    CTC_ERROR_RETURN(_sys_tmm_epe_write_wrr_weight_cfg(lchip, low_weight_sum, high_weight_sum, dp_id));

    return CTC_E_NONE;
}

uint32
_sys_tmm_qmgr_write_weight_to_registor(uint8 lchip, uint16* weight_arr, uint16 (*xg_lg)[2])
{    
    uint16 divisor    = 0;
    uint16 chan_id    = 0;
    uint8  dp_id      = 0;
    uint8  group_id   = 0;
    uint32 cmd        = 0;
    uint32 step       = 0;
    uint32 opt_weight = 0;
    uint16 weight_dp[SYS_TMM_DP_NUM] = {0};

#ifdef PCS_IMG
    QMgrShellIntfWtCfg_m  intf_weight_cfg;
    QMgrShellChWtCfgMem_m      chan_weight;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    weight_dp[0] += xg_lg[0][0];
    weight_dp[0] += xg_lg[0][1];
    weight_dp[1] += xg_lg[1][0];
    weight_dp[1] += xg_lg[1][1];
    
    /*  XG&LG Level WRR     256Depth  */
    CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(weight_arr, SYS_TMM_CHANNEL_NUM, &divisor));
    for(chan_id = 0; chan_id < SYS_TMM_CHANNEL_NUM; chan_id++)
    {
        cmd = DRV_IOR(QMgrShellChWtCfgMem_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, chan_id, cmd, &chan_weight);
        
        opt_weight = weight_arr[chan_id] / divisor;
        
        DRV_IOW_FIELD_NZ(lchip, QMgrShellChWtCfgMem_t, QMgrShellChWtCfgMem_weightCfg_f, 
            &opt_weight, &chan_weight, 0, chan_id);
        cmd = DRV_IOW(QMgrShellChWtCfgMem_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, chan_id, cmd, &chan_weight);
    }

    /*  DP WRR  */
    step = QMgrShellIntfWtCfg_gDp_0_cfgXgWeight_f - QMgrShellIntfWtCfg_gDp_0_cfgLgWeight_f;

    cmd = DRV_IOR(QMgrShellIntfWtCfg_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &intf_weight_cfg);
    for(dp_id = 0; dp_id < SYS_TMM_DP_NUM; dp_id++)
    {
        CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(xg_lg[dp_id], 2, &divisor));
        for(group_id = 0; group_id < 2; group_id++)
        {
            opt_weight = xg_lg[dp_id][group_id] / divisor;
            DRV_IOW_FIELD(lchip, QMgrShellIntfWtCfg_t, 
                QMgrShellIntfWtCfg_gDp_0_cfgLgWeight_f+step*(dp_id*SYS_TMM_DP_NUM+group_id), 
                &opt_weight, &intf_weight_cfg);
        }
    }

    /*  Slice WRR  */
    CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(weight_dp, 2, &divisor));    
    opt_weight = weight_dp[0] /divisor;
    DRV_IOW_FIELD(lchip, QMgrShellIntfWtCfg_t, QMgrShellIntfWtCfg_cfgDp0Weight_f, &opt_weight, &intf_weight_cfg);
    opt_weight = weight_dp[1] /divisor;
    DRV_IOW_FIELD(lchip, QMgrShellIntfWtCfg_t, QMgrShellIntfWtCfg_cfgDp1Weight_f, &opt_weight, &intf_weight_cfg);

    cmd = DRV_IOW(QMgrShellIntfWtCfg_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &intf_weight_cfg);

#else
    QMgrDeqIntfWeightCfg_m  intf_weight_cfg;
    DsQMgrChanWeight_m      chan_weight;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    weight_dp[0] += xg_lg[0][0];
    weight_dp[0] += xg_lg[0][1];
    weight_dp[1] += xg_lg[1][0];
    weight_dp[1] += xg_lg[1][1];
    
    /*  XG&LG Level WRR     256Depth  */
    // FIXME: this is wrong. xg and lg need to calculate gcd respectively
    CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(weight_arr, SYS_TMM_CHANNEL_NUM, &divisor));
    for(chan_id = 0; chan_id < SYS_TMM_CHANNEL_NUM; chan_id++)
    {
        cmd = DRV_IOR(DsQMgrChanWeight_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, chan_id, cmd, &chan_weight);
        
        opt_weight = weight_arr[chan_id] / divisor;
        
        DRV_IOW_FIELD_NZ(lchip, DsQMgrChanWeight_t, DsQMgrChanWeight_weight_f, &opt_weight, &chan_weight, 0, chan_id);
        cmd = DRV_IOW(DsQMgrChanWeight_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, chan_id, cmd, &chan_weight);
    }

    /*  DP WRR  */
    step = QMgrDeqIntfWeightCfg_gDp_0_cfgXgWeight_f - QMgrDeqIntfWeightCfg_gDp_0_cfgLgWeight_f;

    cmd = DRV_IOR(QMgrDeqIntfWeightCfg_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &intf_weight_cfg);
    for(dp_id = 0; dp_id < SYS_TMM_DP_NUM; dp_id++)
    {
        CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(xg_lg[dp_id], 2, &divisor));
        for(group_id = 0; group_id < 2; group_id++)
        {
            opt_weight = xg_lg[dp_id][group_id] / divisor;
            DRV_IOW_FIELD(lchip, QMgrDeqIntfWeightCfg_t, 
                QMgrDeqIntfWeightCfg_gDp_0_cfgLgWeight_f+step*(dp_id*SYS_TMM_DP_NUM+group_id), 
                &opt_weight, &intf_weight_cfg);
        }
    }

    /*  Slice WRR  */
    CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(weight_dp, 2, &divisor));    
    opt_weight = weight_dp[0] /divisor;
    DRV_IOW_FIELD(lchip, QMgrDeqIntfWeightCfg_t, QMgrDeqIntfWeightCfg_cfgDp0Weight_f, &opt_weight, &intf_weight_cfg);
    opt_weight = weight_dp[1] /divisor;
    DRV_IOW_FIELD(lchip, QMgrDeqIntfWeightCfg_t, QMgrDeqIntfWeightCfg_cfgDp1Weight_f, &opt_weight, &intf_weight_cfg);

    cmd = DRV_IOW(QMgrDeqIntfWeightCfg_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &intf_weight_cfg);
#endif
    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

/*
 * @brief       DsQMgrChanWeight -- weight
 *              QMgrDeqIntWeightCfg -- gDp_(0/1)_cfg(L/X)gWeight
 *                                 -- cfgDp(0/1)Weight 
 *              
 */
STATIC int32
_sys_tmm_datapath_set_qmgr_wrr_weight(uint8 lchip)
{
    uint16 xg_lg[2][2]  = {{0}};
    uint16 speed        = 0;
    uint16 lport        = 0;
    uint8  dp           = 0;
    uint16 weight       = 0; 
    uint16 weight_arr[SYS_TMM_CHANNEL_NUM] = {0};
    sys_datapath_lport_attr_t* port_attr = NULL;
    uint8  loop_chan_dp0[2] = {114, 116};
    uint8  loop_chan_dp1[2] = {242, 244};
    uint8  loop_idx;

    /*network & misc port*/
    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(!port_attr || port_attr->port_type == SYS_DMPS_RSV_PORT || 
            port_attr->port_type == SYS_DMPS_INACTIVE_NETWORK_PORT || (CTC_PORT_SPEED_MAX <= port_attr->speed_mode));
        SYS_CONDITION_RETURN(SYS_TMM_CHANNEL_NUM <= port_attr->chan_id, CTC_E_INVALID_PARAM);
        dp = SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id);
        SYS_DATAPATH_SPEED_TO_WRRCFG(port_attr->speed_mode, weight);
        SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);
        if(speed < 50)
        {
            xg_lg[dp][0]  += weight;
        }
        else
        {
            xg_lg[dp][1]  += weight; 
        }
        weight_arr[port_attr->chan_id] = weight;

        /*loop chan 114 & 116*/
        if(loop_chan_dp0[0] == port_attr->chan_id)
        {
            for(loop_idx = 1; loop_idx < 2; loop_idx++)
            {
                xg_lg[dp][1]  += weight;
                weight_arr[loop_chan_dp0[loop_idx]] = weight;
            }
        }
        else if(loop_chan_dp1[0] == port_attr->chan_id)
        {
            for(loop_idx = 1; loop_idx < 2; loop_idx++)
            {
                xg_lg[dp][1]  += weight;
                weight_arr[loop_chan_dp1[loop_idx]] = weight;
            }
        }

        /*xpipe pmac*/
        SYS_CONDITION_CONTINUE((CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en) || (CTC_PORT_XPIPE_TYPE_6 == port_attr->xpipe_en));
        if(speed < 50)
        {
            xg_lg[dp][0]  += weight;
        }
        else
        {
            xg_lg[dp][1]  += weight; 
        }
        weight_arr[port_attr->pmac_chanid] = weight;
    }   
    
    CTC_ERROR_RETURN(_sys_tmm_qmgr_write_weight_to_registor(lchip, weight_arr, xg_lg));

    return CTC_E_NONE;
}

/*
 * @note        this code can be optimized.
 *              remember to came back to finish it.
 *              kegc
 * @note        weight_arr      TXQM --- mac
 *              weight_of_txqms  a groups of channel defined by txqm[0...3]ReqEn
 * 
 */
uint32
_sys_tmm_bufretrv_cal_divisors_for_WtCfgMem(uint16* weight_arr, uint16* divisors)
{
    uint8  dp_chan_id;
    uint8  vtxqm;
    uint8  vtxqm_chan;
    uint16 count;
    uint16 weight_of_txqms[5][40] = {{0}};  //index [virtual txqm id][chan id in single virtual txqm id]

    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        _sys_tmm_datapath_get_virtual_txqm_chan(dp_chan_id, &vtxqm, &vtxqm_chan);
        weight_of_txqms[vtxqm][vtxqm_chan] = weight_arr[dp_chan_id];
    }

    for(vtxqm = 0; vtxqm < 5; vtxqm++)
    {
        count = (4 == vtxqm) ? 16 : 40;
        CTC_ERROR_RETURN(sys_usw_datapath_get_gcd((uint16*)(weight_of_txqms[vtxqm]), count,  &(divisors[vtxqm])));
    }

    return CTC_E_NONE;
}


/* @brief           set both EpeWfCfgMem and PkfWFCfgMem 
 * @weight_arr      origin weight, index by channel id 
 * @note            in @weight_arr, none-active channel value should be 0
 */
uint32
_sys_tmm_datapath_bufretrv_write_weight_to_reigistor(uint8 lchip, uint16* weight_arr, uint8 dp_id)
{
    uint8  vtxqm;
    uint8  dp_chan_id;
    uint32 opt_weight     = 0;
    uint32 cmd            = 0;
    uint32 entry_id       = 0;
    uint16 divisors[5]    = {0};  //index vt_txqm 0~4
    BufRetrvDPEpeWtCfgMem_m epe_weight_cfg;
    BufRetrvDPPktWtCfgMem_m pkt_weight_cfg;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    _sys_tmm_bufretrv_cal_divisors_for_WtCfgMem(weight_arr, divisors);

    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        _sys_tmm_datapath_get_virtual_txqm_chan(dp_chan_id, &vtxqm, NULL);
        
        entry_id = DRV_INS(dp_id, dp_chan_id);
        opt_weight = weight_arr[dp_chan_id] / divisors[vtxqm]; 

        /* BufRetrvDPEpeWfCfgMem */
        cmd = DRV_IOR(BufRetrvDPEpeWtCfgMem_t,  DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &epe_weight_cfg);

        DRV_IOW_FIELD_NZ(lchip, BufRetrvDPEpeWtCfgMem_t,  BufRetrvDPEpeWtCfgMem_weight_f, 
            &opt_weight, &epe_weight_cfg, dp_id, dp_chan_id);
        cmd = DRV_IOW(BufRetrvDPEpeWtCfgMem_t,  DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &epe_weight_cfg);

        /* BufRetrvDPPktWfCfgMem */
        cmd = DRV_IOR(BufRetrvDPPktWtCfgMem_t,  DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &pkt_weight_cfg);

        DRV_IOW_FIELD_NZ(lchip, BufRetrvDPPktWtCfgMem_t,  BufRetrvDPPktWtCfgMem_weight_f, 
            &opt_weight, &pkt_weight_cfg, dp_id, dp_chan_id);
        cmd = DRV_IOW(BufRetrvDPPktWtCfgMem_t,  DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &pkt_weight_cfg);
    }

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

uint32
_sys_tmm_datapath_bufretrv_wrr_ctl(uint8 lchip, uint16 weight_sum[5], uint8 dp_id)
{
    uint32 entry_id = 0;
    uint32 cmd = 0;
    uint16 divisor = 0;
    uint32 opt_weight = 0;
    uint16 step   = BufRetrvDPWrrCtl_txqm1WtCfg_f - BufRetrvDPWrrCtl_txqm0WtCfg_f;
    uint8  dp_txqm_id;
    BufRetrvDPWrrCtl_m wrr_ctl;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    entry_id = DRV_INS(dp_id, 0);
    CTC_ERROR_RETURN(sys_usw_datapath_get_gcd(weight_sum, 5, &divisor));

    /*network*/
    cmd = DRV_IOR(BufRetrvDPWrrCtl_t,  DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &wrr_ctl);
    
    for(dp_txqm_id = 0; dp_txqm_id < 4; dp_txqm_id++)
    {
        opt_weight = weight_sum[dp_txqm_id] / divisor;
        DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t,  BufRetrvDPWrrCtl_txqm0WtCfg_f+step*dp_txqm_id, 
            &opt_weight, &wrr_ctl, dp_id, 0);
    }

    /*misc*/
    opt_weight = weight_sum[4] / divisor;
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t,  BufRetrvDPWrrCtl_miscGroupWtCfg_f, 
        &opt_weight, &wrr_ctl, dp_id, 0);
    
    cmd = DRV_IOW(BufRetrvDPWrrCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &wrr_ctl);

    DP_DEBUG_FUNCTION_RETURN_PRINT();
        

    return CTC_E_NONE;
}

/*
Do config virtual txqm id related chan enable
*/
STATIC int32
_sys_tmm_datapath_set_virtual_txqm_en(uint8 lchip, uint8 dp_id)
{
    uint32 cmd       = 0;
    uint32 entry_id  = 0;
    uint32 bitmap[2] = {0};
    BufRetrvDPWrrCtl_m wrr_ctl;

    entry_id = DRV_INS(dp_id, 0);
    cmd = DRV_IOR(BufRetrvDPWrrCtl_t,  DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &wrr_ctl);

    sal_memset(bitmap, 0, sizeof(bitmap));
    bitmap[0] = 0xffff;      /* channel: 0-15 */
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_txqm0ReqEn_f, bitmap, &wrr_ctl, dp_id, 0);
    
    sal_memset(bitmap, 0, sizeof(bitmap));
    bitmap[0] = 0xffff;      /* channel: 16-31 */
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_txqm1ReqEn_f, bitmap, &wrr_ctl, dp_id, 0);
    
    sal_memset(bitmap, 0, sizeof(bitmap));
    bitmap[0] = 0xffffffff;  /* channel: 32-39, 48-79*/
    bitmap[1] = 0xff;
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_txqm2ReqEn_f, bitmap, &wrr_ctl, dp_id, 0);
    
    sal_memset(bitmap, 0, sizeof(bitmap));
    bitmap[0] = 0xffffffff;  /* channel: 40-47, 80-111 */
    bitmap[1] = 0xff;
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_txqm3ReqEn_f, bitmap, &wrr_ctl, dp_id, 0);

    cmd = DRV_IOW(BufRetrvDPWrrCtl_t,  DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &wrr_ctl);

    return CTC_E_NONE;
}


/*Here vtxqm means Virtual txqm id. It is NOT mac txqm id. It is used for ASIC internal algorithms. 
Mac-Chan mapping will not influence virtual txqm id.*/
STATIC int32
_sys_tmm_datapath_set_bufretrv_wrr_weight(uint8 lchip, uint8 dp_id)
{
    uint8  vtxqm         = 0;
    uint8  vxtqm_chan    = 0;
    uint8  dp_chan_id    = 0;
    uint16 lport         = 0;
    uint16 wrrbase       = 0;
    uint16 weight_sum[5] = {0};    /* DP vtxqm:0 1 2 3; misc: 4 */
    uint16 weight_arr[SYS_TMM_CHANNEL_NUM_PER_DP] = {0};
    sys_datapath_lport_attr_t* port_attr = NULL;
    uint8  loop_chan = 116;

    /* important */
    _sys_tmm_datapath_set_virtual_txqm_en(lchip, dp_id);
    
    /* get net channel info */
    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(!port_attr || port_attr->port_type == SYS_DMPS_RSV_PORT || port_attr->port_type == SYS_DMPS_INACTIVE_NETWORK_PORT);

        /*only port in this dp will be operated*/
        SYS_CONDITION_CONTINUE((dp_id != SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id)) || (CTC_PORT_SPEED_MAX <= port_attr->speed_mode));

        wrrbase = 0;
        SYS_DATAPATH_SPEED_TO_WRRCFG(port_attr->speed_mode, wrrbase);

        dp_chan_id = SYS_TMM_GET_CHANN_PER_DP((CTC_PORT_XPIPE_TYPE_6 == port_attr->xpipe_en) ? 
            port_attr->pmac_chanid : port_attr->chan_id);
        _sys_tmm_datapath_get_virtual_txqm_chan(dp_chan_id, &vtxqm, &vxtqm_chan);
        
        weight_sum[vtxqm]     += wrrbase;
        weight_arr[dp_chan_id] = wrrbase;

        /*xpipe pmac*/
        SYS_CONDITION_CONTINUE((CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en) || (CTC_PORT_XPIPE_TYPE_6 == port_attr->xpipe_en));
        
        dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(port_attr->pmac_chanid);
        _sys_tmm_datapath_get_virtual_txqm_chan(dp_chan_id, &vtxqm, NULL);
        
        weight_sum[vtxqm]     += wrrbase;
        weight_arr[dp_chan_id] = wrrbase;
    }

    /*loop chan 114 & 116 (in 2 dp)*/
    SYS_DATAPATH_SPEED_TO_WRRCFG(CTC_PORT_SPEED_200G, wrrbase);
    _sys_tmm_datapath_get_virtual_txqm_chan(loop_chan, &vtxqm, &vxtqm_chan);
    weight_sum[vtxqm]              += wrrbase;
    weight_arr[loop_chan] = wrrbase;

    /*write tables*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_bufretrv_write_weight_to_reigistor(lchip, weight_arr, dp_id));
    /* txqm0..3ReqEn  including network & misc*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_bufretrv_wrr_ctl(lchip, weight_sum, dp_id));

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_set_netrx_port_chan_mapping1(uint8 lchip, uint16 mac_id, uint8 chan_id)
{
    uint32 cmd        = 0;
    uint32 entry_id   = 0;
    uint32 dp_id      = SYS_TMM_GET_DP_ID_FROM_MACID(mac_id);
    uint32 dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(chan_id);
    uint32 dp_mac_id  = SYS_TMM_GET_MACID_PER_DP(mac_id);
    DsNetRxPortToChanMap_m port_to_chan;

    /*mac to channel*/
    entry_id = DRV_INS(dp_id, dp_mac_id);
    
    cmd = DRV_IOR(DsNetRxPortToChanMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &port_to_chan));

    DRV_IOW_FIELD_NZ(lchip, DsNetRxPortToChanMap_t, DsNetRxPortToChanMap_chan_f, &dp_chan_id, &port_to_chan, 
        dp_id, dp_mac_id);

    cmd = DRV_IOW(DsNetRxPortToChanMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &port_to_chan));

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_set_netrx_port_chan_mapping2(uint8 lchip, uint16 mac_id, uint8 chan_id)
{
    uint32 cmd        = 0;
    uint32 entry_id   = 0;
    uint32 dp_id      = SYS_TMM_GET_DP_ID_FROM_MACID(mac_id);
    uint32 dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(chan_id);
    uint32 dp_mac_id  = SYS_TMM_GET_MACID_PER_DP(mac_id);
    DsNetRxChanToPortMap_m chan_to_port;

    /*channel to mac*/
    entry_id = DRV_INS(dp_id, dp_chan_id);
    
    cmd = DRV_IOR(DsNetRxChanToPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &chan_to_port));
    
    DRV_IOW_FIELD_NZ(lchip, DsNetRxChanToPortMap_t, DsNetRxChanToPortMap_portId_f, &dp_mac_id, &chan_to_port, 
        dp_id, dp_chan_id);
    
    cmd = DRV_IOW(DsNetRxChanToPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &chan_to_port));

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_set_netrx_port_chan_mapping(uint8 lchip, uint16 mac_id, uint8 chan_id)
{
    uint32 cmd        = 0;
    uint32 entry_id   = 0;
    uint32 dp_id      = SYS_TMM_GET_DP_ID_FROM_MACID(mac_id);
    uint32 dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(chan_id);
    uint32 dp_mac_id  = SYS_TMM_GET_MACID_PER_DP(mac_id);
    DsNetRxPortToChanMap_m port_to_chan;
    DsNetRxChanToPortMap_m chan_to_port;

    /*mac to channel*/
    entry_id = DRV_INS(dp_id, dp_mac_id);
    
    cmd = DRV_IOR(DsNetRxPortToChanMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &port_to_chan));

    DRV_IOW_FIELD_NZ(lchip, DsNetRxPortToChanMap_t, DsNetRxPortToChanMap_chan_f, &dp_chan_id, &port_to_chan, 
        dp_id, dp_mac_id);

    cmd = DRV_IOW(DsNetRxPortToChanMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &port_to_chan));

    /*channel to mac*/
    entry_id = DRV_INS(dp_id, dp_chan_id);
    
    cmd = DRV_IOR(DsNetRxChanToPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &chan_to_port));
    
    DRV_IOW_FIELD_NZ(lchip, DsNetRxChanToPortMap_t, DsNetRxChanToPortMap_portId_f, &dp_mac_id, &chan_to_port, 
        dp_id, dp_chan_id);
    
    cmd = DRV_IOW(DsNetRxChanToPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &chan_to_port));

    return CTC_E_NONE;
}

/*
 * @brief:      DsNetRxBufAdmissionCtl & NetRxBufManagement
 * @notice:     This function is to improving packet drop homogeneity.
 * @detial:     NetRxBufManagement:
 *              TXQMs share one buffer pool. Every TXQM has four level waterlines. If package in 
 *              buffer cross the waterlines, will couse pagckage drop. Only configure low and mid.
 */
int32
_sys_tmm_datapath_set_dp_netrx_buf(uint8 lchip, uint8 dp_id)
{
    uint16 dp_txqm                 = 0;
    uint16 txqm_mac                = 0;
    uint16 lport                   = 0;
    uint16 mac_id                  = 0;
    const uint32 low_threshold_pre = 320;
    const uint32 low_threshold_adj = 2;
    uint32 entry_id                = 0;
    uint32 val_32                  = 0;
    uint32 cmd                     = 0;
    uint32 guarantee_depth         = 0; //value * factor
    uint32 divisor                 = 0;
    uint32 speed                   = 0;
    uint32 dp_mac_id               = 0;
    uint32 txqm_bw_max             = 0;
    uint32 mid_threshold_adj       = 0;
    uint32 low_thrd_final          = 0;
    uint32 mid_thrd_final          = 0;
    uint32 txqms_bandwith[SYS_TMM_TXQM_NUM_PER_DP]     = {0};
    uint32 guarantee_depth_ge[SYS_TMM_TXQM_NUM_PER_DP] = {0};
    uint32 guarantee_depth_xg[SYS_TMM_TXQM_NUM_PER_DP] = {0};
    uint32 low_threshold[SYS_TMM_TXQM_NUM_PER_DP]      = {0};
    NetRxBufManagement_m buf_manage;
    DsNetRxBufAdmissionCtl_m buf_admission_ctl;
    sys_datapath_lport_attr_t* port_attr = NULL;

    /*step 0. calculate all txqms bw*/
    for(dp_txqm = 0; dp_txqm < SYS_TMM_TXQM_NUM_PER_DP; dp_txqm++)
    {
        for(txqm_mac = 0; txqm_mac < SYS_TMM_MAX_MAC_NUM_PER_TXQM; txqm_mac++)
        {
            dp_mac_id = dp_txqm * SYS_TMM_MAX_MAC_NUM_PER_TXQM + txqm_mac;
            mac_id    = dp_id * SYS_TMM_MAX_MAC_NUM_PER_DP + dp_mac_id;
            lport     = sys_usw_datapath_get_lport_with_mac(lchip, mac_id);
            SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == lport);
            port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
            SYS_CONDITION_CONTINUE((NULL == port_attr) || (port_attr->port_type != SYS_DMPS_NETWORK_PORT));
            /*only NW ports are calculated*/

            SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);
            txqms_bandwith[dp_txqm] += speed;

            /*xpipe pmac*/
            SYS_CONDITION_CONTINUE(CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en);
            txqms_bandwith[dp_txqm] += speed;
        }
    }

    /*step 1. look up maximum bw*/
    for(dp_txqm = 0; dp_txqm < SYS_TMM_TXQM_NUM_PER_DP; dp_txqm++)
    {
        if(txqm_bw_max < txqms_bandwith[dp_txqm])
        {
            txqm_bw_max = txqms_bandwith[dp_txqm];
        }
    }
    SYS_CONDITION_RETURN((0 == txqm_bw_max), CTC_E_NONE);

    for(dp_txqm = 0; dp_txqm < SYS_TMM_TXQM_NUM_PER_DP; dp_txqm++)
    {
        guarantee_depth_ge[dp_txqm] = low_threshold_pre / txqm_bw_max;
        guarantee_depth_xg[dp_txqm] = low_threshold_pre * 10 / txqm_bw_max;
        /*compensation factor for cg/lg/xxvg*/
        divisor = (400 == txqms_bandwith[dp_txqm] ? 5 : 6);

        for(txqm_mac = 0; txqm_mac < SYS_TMM_MAX_MAC_NUM_PER_TXQM; txqm_mac++)
        {
            dp_mac_id = dp_txqm * SYS_TMM_MAX_MAC_NUM_PER_TXQM + txqm_mac;
            mac_id    = dp_id * SYS_TMM_MAX_MAC_NUM_PER_DP + dp_mac_id;
            lport     = sys_usw_datapath_get_lport_with_mac(lchip, mac_id);
            SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == lport);
            port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
            SYS_CONDITION_CONTINUE((NULL == port_attr) || (port_attr->port_type != SYS_DMPS_NETWORK_PORT));
            SYS_CONDITION_CONTINUE(port_attr->port_type != SYS_DMPS_NETWORK_PORT);

            /*step 2. calculate guarantee buffer depth*/
            SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);
            /*10G/25G/../400G*/
            if(speed >= 10)
            {
                guarantee_depth = (SYS_SCALE_FACTOR * speed * guarantee_depth_xg[dp_txqm]) / 10;
                if(speed > 10)
                {
                    guarantee_depth -= ((SYS_SCALE_FACTOR * guarantee_depth_xg[dp_txqm]) / divisor);
                }
            }
            /*1G/5G*/
            else
            {
                guarantee_depth = SYS_SCALE_FACTOR * speed * guarantee_depth_ge[dp_txqm];
            }
            /*cfg DsNetRxBufAdmissionCtl*/
            entry_id  = DRV_INS(dp_id, dp_mac_id);
            val_32    = guarantee_depth / SYS_SCALE_FACTOR;
            cmd = DRV_IOR(DsNetRxBufAdmissionCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &buf_admission_ctl));
            DRV_IOW_FIELD_NZ(lchip, DsNetRxBufAdmissionCtl_t, 
                DsNetRxBufAdmissionCtl_cfgGuaranteeBufferNum_f, &val_32, &buf_admission_ctl, dp_id, dp_mac_id);
            cmd = DRV_IOW(DsNetRxBufAdmissionCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &buf_admission_ctl));

            low_threshold[dp_txqm] += guarantee_depth;

            /*cfg xpipe pmac*/
            SYS_CONDITION_CONTINUE(CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en);

            dp_mac_id = SYS_TMM_GET_MACID_PER_DP(port_attr->pmac_id);
            entry_id  = DRV_INS(dp_id, dp_mac_id);
            val_32    = guarantee_depth / SYS_SCALE_FACTOR;
            cmd = DRV_IOR(DsNetRxBufAdmissionCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &buf_admission_ctl));
            DRV_IOW_FIELD_NZ(lchip, DsNetRxBufAdmissionCtl_t, 
                DsNetRxBufAdmissionCtl_cfgGuaranteeBufferNum_f, &val_32, &buf_admission_ctl, dp_id, dp_mac_id);
            cmd = DRV_IOW(DsNetRxBufAdmissionCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &buf_admission_ctl));

            low_threshold[dp_txqm] += guarantee_depth;
        }
        
        /*step 3. calculate low/mid threshold*/
        /* ceil. low_threshold no longer scaled by 1000 */
        if(100 * SYS_SCALE_FACTOR > low_threshold[dp_txqm])
        {
            low_threshold[dp_txqm] = 100 * SYS_SCALE_FACTOR;
        }
        mid_threshold_adj = 80 * txqms_bandwith[dp_txqm] / txqm_bw_max;

        low_thrd_final = low_threshold[dp_txqm] / SYS_SCALE_FACTOR + low_threshold_adj;
        mid_thrd_final = low_thrd_final + mid_threshold_adj;

        entry_id = DRV_INS(dp_id, 0);
        cmd = DRV_IOR(NetRxBufManagement_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &buf_manage));
        val_32 = low_thrd_final;
        DRV_IOW_FIELD_NZ(lchip, NetRxBufManagement_t, NetRxBufManagement_cfgLowThrd0_f + dp_txqm, 
            &val_32, &buf_manage, dp_id, 0);
        val_32 = mid_thrd_final;
        DRV_IOW_FIELD_NZ(lchip, NetRxBufManagement_t, NetRxBufManagement_cfgMidThrd0_f + dp_txqm, 
            &val_32, &buf_manage, dp_id, 0);
        cmd = DRV_IOW(NetRxBufManagement_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &buf_manage));
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_netrx_other_cfg(uint8 lchip, uint8 dp_id)
{
    uint32 cmd;
    uint32 entry_id;
    uint32 value;
    NetRxAdmissionCfg_m ntrx_cfg;

    /*write NetRxAdmissionCfg.cfgLongPktPri 1, to avoid long packet cut in super wide bandwidth*/
    entry_id = DRV_INS(dp_id, 0);
    value = 1;
    cmd = DRV_IOR(NetRxAdmissionCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &ntrx_cfg));
    DRV_IOW_FIELD_NZ(lchip, NetRxAdmissionCfg_t, NetRxAdmissionCfg_cfgLongPktPri_f, &value, &ntrx_cfg, dp_id, 0);
    cmd = DRV_IOW(NetRxAdmissionCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &ntrx_cfg));

    return CTC_E_NONE;
}

#if (SDB_MEM_MODEL != SDB_MODE)
STATIC int32
_sys_tmm_datapath_netrx_init(uint8 lchip, uint8 dp_id)
{
    uint16 mac_id;
    uint8  chan_id;
    uint8  dp_chan_id;
    uint8  quad_cnt            = 0;
    uint8  logic_serdes_id_prv = SYS_TMM_USELESS_ID8;
    uint8  logic_serdes_id_cur = SYS_TMM_USELESS_ID8;

    /*network port mapping    based on soft table mapping*/
    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        SYS_CONDITION_CONTINUE(SYS_TMM_IS_MISC_CHAN(dp_id, dp_chan_id));
        
        SYS_CONDITION_CONTINUE(SYS_CHAN_LPORT_OCCUPY_RSV == p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag);

        logic_serdes_id_prv = logic_serdes_id_cur;
        logic_serdes_id_cur = p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].logic_serdes_id;

        SYS_CONDITION_CONTINUE(SYS_TMM_MAX_SERDES_NUM <= logic_serdes_id_cur);

        if(logic_serdes_id_prv == logic_serdes_id_cur)
        {
            quad_cnt++;
        }
        else
        {
            quad_cnt = 0;
        }
        mac_id = g_lane_2_pcs_mac_map[logic_serdes_id_cur].mac_id + quad_cnt;

        chan_id = dp_id*SYS_TMM_CHANNEL_NUM_PER_DP + dp_chan_id;
        
        /*mac-chan mapping    only do in init*/ 
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_netrx_port_chan_mapping(lchip, mac_id, chan_id));
    }
    /*wrr weight*/
    _sys_tmm_datapath_set_dp_netrx_wrr_weight(lchip, dp_id);

    _sys_tmm_datapath_set_dp_netrx_buf(lchip, dp_id);

    _sys_tmm_datapath_netrx_other_cfg(lchip, dp_id);

    return CTC_E_NONE;
}
#endif

#define __BUFFER__

#ifdef EMULATION_ENV
int32
_sys_tmm_datapath_qmgr_dest_port(uint8 lchip)
{
    uint32 cmd       = 0;
    uint32 tmp_val32 = 0;
    uint32 entry_id  = 0;
    uint16 buf_size  = 50;    //_sys_tmm_datapath_get_qmgrshell_chan_max_buf
    uint16 st        = 0;
    uint16 ed        = 0;
    uint16 chan_id   = 0;
    QMgrShellDestPortInfo_m port_info;
    QMgrShellDestPortConfig_m port_config;

    for(chan_id = 0; chan_id < SYS_TMM_CHANNEL_NUM; chan_id++)
    {
        entry_id = DRV_INS(0, chan_id);
        
        ed = st + buf_size - 1;
        /* PortInfo */
        cmd = DRV_IOR(QMgrShellDestPortInfo_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &port_info);
    
        tmp_val32 = st;
        DRV_IOW_FIELD_NZ(lchip,QMgrShellDestPortInfo_t, QMgrShellDestPortInfo_wrPtr_f, &tmp_val32, &port_info, 0, chan_id);
        DRV_IOW_FIELD_NZ(lchip,QMgrShellDestPortInfo_t, QMgrShellDestPortInfo_rdPtr_f, &tmp_val32, &port_info, 0, chan_id);
        tmp_val32 = 0;
        DRV_IOW_FIELD_NZ(lchip,QMgrShellDestPortInfo_t, QMgrShellDestPortInfo_full_f, &tmp_val32, &port_info, 0, chan_id);
    
        cmd = DRV_IOW(QMgrShellDestPortInfo_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &port_info);

        /* PortConfig */
        cmd = DRV_IOR(QMgrShellDestPortConfig_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, chan_id, cmd, &port_config);
       
        tmp_val32 = st;
        DRV_IOW_FIELD_NZ(lchip,QMgrShellDestPortConfig_t, QMgrShellDestPortConfig_startPtr_f, &tmp_val32, &port_config, 0, chan_id);
        tmp_val32 = ed;
        DRV_IOW_FIELD_NZ(lchip,QMgrShellDestPortConfig_t, QMgrShellDestPortConfig_endPtr_f, &tmp_val32, &port_config, 0, chan_id);
    
        cmd = DRV_IOW(QMgrShellDestPortConfig_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, chan_id, cmd, &port_config);

        st = ed + 1;

        if(ed >= 16384)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% %s: QMgrShell buffer size generate mistake !\n", __FUNCTION__);
        }
    }

    return CTC_E_NONE;
}
#endif

/*check credit: qmgr, bufretrv, epe, nettx*/
int32
_sys_tmm_datapath_check_credit_sum(uint8 lchip, uint8 dp_id)
{
    uint8   chan_id;
    uint8   dp_chan_id;
    uint8   dp_txqm;
    uint16  lport;
    uint16  speed;
    uint32  credit;
    uint32  sum_qmgr  = 0;
    uint32  sum_brsop = 0;
    uint32  sum_brbdy = 0;
    uint32  sum_epe[SYS_TMM_TXQM_NUM_PER_DP]  = {0};
    uint32  sum_nttx[SYS_TMM_TXQM_NUM_PER_DP] = {0};
    sys_datapath_bufsz_step_t  step           = {0};
    sys_datapath_lport_attr_t* port_attr      = NULL;

    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        /*0. info collect*/
        chan_id = SYS_GET_CHANNEL_BY_DP_CHANID(dp_chan_id, dp_id);
        SYS_CONDITION_CONTINUE(SYS_TMM_USELESS_ID8 == chan_id);
        lport = sys_usw_datapath_get_lport_with_chan(lchip, chan_id);
        SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == lport);
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE((!port_attr) || (port_attr->port_type == SYS_DMPS_RSV_PORT) || 
            (port_attr->port_type == SYS_DMPS_INACTIVE_NETWORK_PORT) || (CTC_PORT_SPEED_MAX <= port_attr->speed_mode));
        dp_txqm = SYS_TMM_GET_TXQM_PER_DP(port_attr->txqm_id);
        SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);

        /*considering credit has 10% redundancy, skip 116 occupying resource*/

        /*1. qmgr credit dp sum: network & misc*/
        sum_qmgr += port_attr->q_credit;
        /*xpipe*/
        if((CTC_PORT_XPIPE_TYPE_0 != port_attr->xpipe_en) && (CTC_PORT_XPIPE_TYPE_6 != port_attr->xpipe_en))
        {
            sum_qmgr += port_attr->q_credit;
        }

        /*2. bufretrv credit dp sum: network & misc*/
        sal_memset(&step, 0, sizeof(sys_datapath_bufsz_step_t));
        CTC_ERROR_RETURN(_sys_tmm_datapath_bufretrv_get_credit(lchip, port_attr->speed_mode, &step));

        sum_brsop += step.sop_buf_num;
        sum_brbdy += step.body_buf_num;
        /*xpipe*/
        if((CTC_PORT_XPIPE_TYPE_0 != port_attr->xpipe_en) && (CTC_PORT_XPIPE_TYPE_6 != port_attr->xpipe_en))
        {
            sum_brsop += step.sop_buf_num;
            sum_brbdy += step.body_buf_num;
        }

        SYS_CONDITION_CONTINUE(port_attr->port_type != SYS_DMPS_NETWORK_PORT);

        /*3. epe credit txqm sum: network only*/
        credit = _sys_tmm_datapath_epe_speed_to_credit(speed);
        sum_epe[dp_txqm] += credit;

        /*4. nettx credit txqm sum: network only*/
        credit = _sys_tmm_nettx_speed_to_credit(speed);
        sum_nttx[dp_txqm] += credit;
    }

    /*qmgr credit per dp sum check (512 per dp)*/
    if(sum_qmgr > 512)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% QMgr credit mistake! dp %u, sum is %d \n", dp_id, sum_qmgr);
        return CTC_E_INVALID_CONFIG;
    }
    /*bufretrv credit per dp sum check (sop: 1024 per dp, body: 768 per dp)*/
    if(sum_brsop > 1024)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% BufRetrv sop credit mistake! dp %u, sum is %d \n", dp_id, sum_brsop);
        return CTC_E_INVALID_CONFIG;
    }
    if(sum_brbdy > 768)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% BufRetrv body credit mistake! dp %u, sum is %d \n", dp_id, sum_brbdy);
        return CTC_E_INVALID_CONFIG;
    }
    /*per txqm*/
    for(dp_txqm = 0; dp_txqm < SYS_TMM_TXQM_NUM_PER_DP; dp_txqm++)
    {
        /*epe credit sum check (320 per TXQM)*/
        if(sum_epe[dp_txqm] > 320)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Epe credit mistake! dp %u, dp_txqm %u, sum is %d \n", 
                dp_id, dp_txqm, sum_epe[dp_txqm]);
            return CTC_E_INVALID_CONFIG;
        }
        /*nettx credit sum check (200 per TXQM)*/
        if(sum_nttx[dp_txqm] > 200)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Nettx credit mistake! dp %u, dp_txqm %u, sum is %d \n", 
                dp_id, dp_txqm, sum_nttx[dp_txqm]);
            return CTC_E_INVALID_CONFIG;
        }
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_set_qmgr_credit(uint8 lchip, sys_datapath_lport_attr_t* port_attr, uint8 alloc_type, uint8 enable)
{    
    uint8  chan_id   = 0;
    uint32 speed     = 0;
    uint32 speed_tmp = 0;
    uint32 cmd       = 0;
    
#ifdef PCS_IMG
    QMgrShellChCredit_m ra_credit;
#else
    DsQMgrChanCredit_m ra_credit;
#endif

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    /* validate used network channel */
    if(port_attr->port_type == SYS_DMPS_RSV_PORT)
    {
        return CTC_E_NONE;
    }
    /* validate misc channel */
    if((port_attr->port_type != SYS_DMPS_NETWORK_PORT) && (port_attr->chan_id == SYS_TMM_USELESS_ID8))
    {
        return CTC_E_NONE;
    }

    if(SYS_ALLOC_XPIPE_PMAC == alloc_type)
    {
        chan_id = port_attr->pmac_chanid;
    }
    else
    {
        chan_id = port_attr->chan_id;
    }

    SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed_tmp);
    speed = _sys_tmm_qmgr_speed_to_credit(speed_tmp); 
    if (SYS_DMPS_INACTIVE_NETWORK_PORT == port_attr->port_type)
    {
        speed = 0;
    }

#ifdef PCS_IMG
    cmd = DRV_IOR(QMgrShellChCredit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &ra_credit));

    DRV_IOW_FIELD_NZ(lchip,QMgrShellChCredit_t, QMgrShellChCredit_credit_f, &speed, &ra_credit, 0, chan_id);
    
    cmd = DRV_IOW(QMgrShellChCredit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &ra_credit));
#else
    cmd = DRV_IOR(DsQMgrChanCredit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &ra_credit));

    DRV_IOW_FIELD_NZ(lchip, DsQMgrChanCredit_t, DsQMgrChanCredit_credit_f, &speed, &ra_credit, 0, chan_id);
    
    cmd = DRV_IOW(DsQMgrChanCredit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &ra_credit));
#endif

    /*loop chan 114 & 116*/
    if(114 == SYS_TMM_GET_CHANN_PER_DP(chan_id))
    {
        chan_id += 2;
#ifdef PCS_IMG
        cmd = DRV_IOR(QMgrShellChCredit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &ra_credit));

        DRV_IOW_FIELD_NZ(lchip,QMgrShellChCredit_t, QMgrShellChCredit_credit_f, &speed, &ra_credit, 0, chan_id);
        
        cmd = DRV_IOW(QMgrShellChCredit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &ra_credit));
#else
        cmd = DRV_IOR(DsQMgrChanCredit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &ra_credit));

        DRV_IOW_FIELD_NZ(lchip, DsQMgrChanCredit_t, DsQMgrChanCredit_credit_f, &speed, &ra_credit, 0, chan_id);
        
        cmd = DRV_IOW(DsQMgrChanCredit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan_id, cmd, &ra_credit));
#endif
    }

    port_attr->q_credit = (uint8)speed;

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

/* bug fixing: 100G R4 underrun. TM2 image has a little fault that cfgSpChan will be given a value 
 * at initial time. We overwrite it. In the future, we will consider rebuild this function.
 */
int32
_sys_tmm_datapath_set_sp_chan(uint8 lchip, uint8 dp_id)
{
    uint8  i;
    uint32 cmd       = 0;
    uint32 entry_id  = 0;
    uint32 tmp_val32 = 0x7f;
    uint32 step      = BufRetrvDPWrrCtl_cfgSpChan1_f - BufRetrvDPWrrCtl_cfgSpChan0_f;
    BufRetrvDPWrrCtl_m wrr_ctl;

    entry_id = DRV_INS(dp_id, 0);
    cmd = DRV_IOR(BufRetrvDPWrrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &wrr_ctl));
    
    for(i = 0; i < 8; i++)
    {
        DRV_IOW_FIELD_NZ(lchip, BufRetrvDPWrrCtl_t, BufRetrvDPWrrCtl_cfgSpChan0_f + step*i, &tmp_val32, &wrr_ctl, dp_id, 0);
    }
    
    cmd = DRV_IOW(BufRetrvDPWrrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &wrr_ctl));

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_qmgrshell_chan_wr_en(uint8 lchip, sys_datapath_lport_attr_t* port_attr)
{
    uint32 entry_id = 0;
    uint32 cmd      = 0;
    uint32 data[8]  = {0};  // 256 bit
    
    entry_id = DRV_INS(0, 0);
    cmd = DRV_IOR(QMgrShellChanWrEnCtl_t,  QMgrShellChanWrEnCtl_chanWrEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, entry_id, cmd, data));
    if (SYS_DMPS_INACTIVE_NETWORK_PORT == port_attr->port_type)
    {
        CTC_BMP_UNSET(data, port_attr->chan_id);
    }
    else
    {
        CTC_BMP_SET(data, port_attr->chan_id);
    }
    cmd = DRV_IOW(QMgrShellChanWrEnCtl_t,  QMgrShellChanWrEnCtl_chanWrEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, entry_id, cmd, data));

    return CTC_E_NONE;
}

#if (SDB_MEM_MODEL != SDB_MODE)
STATIC int32
_sys_tmm_datapath_set_qmgr_misc_en(uint8 lchip, uint8 en_flag)
{
    uint32 value = ((TRUE == en_flag) ? 1 : 0);
    uint32 cmd   = DRV_IOW(QMgrMsgMiscDrainEnable_t, QMgrMsgMiscDrainEnable_freePtrDrainEnable_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    return CTC_E_NONE;
}

/* @brief: set credit for BufRetrv
 *
 */
STATIC int32
_sys_tmm_datapath_qmgr_init(uint8 lchip)
{
    uint8   dp_id;
    uint16  lport    = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;

    /*notice: this code will set credit for rsv port not only network port*/
    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE((!port_attr) || (port_attr->port_type == SYS_DMPS_RSV_PORT));

        /* validate misc channel */
        SYS_CONDITION_CONTINUE((port_attr->port_type != SYS_DMPS_NETWORK_PORT) && (port_attr->chan_id == SYS_TMM_USELESS_ID8));
        SYS_CONDITION_CONTINUE(CTC_PORT_SPEED_MAX <= port_attr->speed_mode);

#ifdef PCS_IMG
        CTC_ERROR_RETURN(_sys_tmm_datapath_qmgrshell_chan_wr_en(lchip, port_attr));
#endif
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_credit(lchip, port_attr, SYS_ALLOC_NORMAL, TRUE));
    }

    for(dp_id = 0; dp_id < SYS_TMM_DP_NUM; dp_id++)
    {
        /*check credit: qmgr, bufretrv, epe, nettx*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_check_credit_sum(lchip, dp_id));
        /*set qmgr xg lg chan en*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_xg_lg_enable(lchip, dp_id));
    }
    /*two DPs calculated together*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_wrr_weight(lchip));

    /*100G R4 underrun*/
    for(dp_id = 0; dp_id < SYS_TMM_DP_NUM; dp_id++)
    {
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_sp_chan(lchip, dp_id));
    }

    /*QMgrMsgMiscDrainEnable.freePtrDrainEnable set 1*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_misc_en(lchip, TRUE));

#ifdef PCS_IMG
    CTC_ERROR_RETURN(_sys_tmm_datapath_qmgr_dest_port(lchip));
#endif

    return CTC_E_NONE;
}
#endif

/*
 * @brief       used to configure all neccery tables 
 *              in BufRetrv moudle   
 */
int32
_sys_tmm_datapath_bufretrv_get_credit(uint8 lchip, uint8 speed_mode, sys_datapath_bufsz_step_t *step)
{  
    uint16 speed   = 0;
    uint8  i       = 0;
    const uint16 speed_num = 9;
    const uint16 speed_lines[] = {0, 9, 10, 25, 40, 50, 100, 200, 400};    // sizeof speed_lines must be speed_num
    const uint16 credits[][3] = {   /*br_credit, sop buf, body buf, speed*/
                                     {0,         0,       0 },   //MAX
                                     {2,         4,       3 },    //less than 10G
                                     {2,         5,       5 },    //10G
                                     {3,         12,      8 },    //25G
                                     {5,         20,      15},    //40G
                                     {6,         24,      18},    //50G
                                     {12,        48,      30},    //100G
                                     {24,        96,      60},    //200G
                                     {48,        192,     80}};    //400G

    SYS_DATAPATH_MODE_TO_SPEED(speed_mode, speed);

    while((i < speed_num) && (speed > speed_lines[i]))
    {
        i++;
    }

    SYS_CONDITION_RETURN((i >= speed_num), CTC_E_INVALID_PARAM);

    step->br_credit_cfg = credits[i][0];
    step->sop_buf_num = credits[i][1];
    step->body_buf_num = credits[i][2];
    
    return CTC_E_NONE;
}

/*
 * @brief       configure all nesessary credit tables
 * */
STATIC int32
_sys_tmm_datapath_set_bufretrv_credit(uint8 lchip, uint8 chan_id, uint8 speed_mode)
{    
    uint32   cmd        = 0;
    uint32   tmp_val32  = 0;
    uint32   entry_id   = 0;
    uint8    dp_id      = SYS_TMM_GET_DP_ID_FROM_CHANID(chan_id);
    uint8    dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(chan_id);
    BufRetrvDPBufCredit_m        buf_credit;
    BufRetrvDPCreditConfigMem_m  body_sop_credit;
    sys_datapath_bufsz_step_t    step = {0};

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    entry_id = DRV_INS(dp_id, dp_chan_id);

    CTC_ERROR_RETURN(_sys_tmm_datapath_bufretrv_get_credit(lchip, speed_mode, &step));
    
    /*Buf Credit*/
    cmd = DRV_IOR(BufRetrvDPBufCredit_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &buf_credit);
        
    tmp_val32 = step.br_credit_cfg;
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPBufCredit_t, BufRetrvDPBufCredit_bufCredit_f, &tmp_val32, &buf_credit, 
        dp_id, dp_chan_id);
    
    cmd = DRV_IOW(BufRetrvDPBufCredit_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &buf_credit);


    /*Body Credit*/
    cmd = DRV_IOR(BufRetrvDPCreditConfigMem_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &body_sop_credit);
    
    tmp_val32 = step.sop_buf_num;
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPCreditConfigMem_t, BufRetrvDPCreditConfigMem_sopCreditCfg_f, &tmp_val32, &body_sop_credit, 
        dp_id, dp_chan_id);
    /*Sop Credit */
    tmp_val32= step.body_buf_num;
    DRV_IOW_FIELD_NZ(lchip, BufRetrvDPCreditConfigMem_t, BufRetrvDPCreditConfigMem_bodyCreditCfg_f, &tmp_val32, &body_sop_credit, 
        dp_id, dp_chan_id);
    
    cmd = DRV_IOW(BufRetrvDPCreditConfigMem_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &body_sop_credit);

    DP_DEBUG_FUNCTION_RETURN_PRINT();
        
    return CTC_E_NONE;
}

#if (SDB_MEM_MODEL != SDB_MODE)
STATIC int32
_sys_tmm_datapath_bufretrv_init(uint8 lchip, uint8 dp_id)
{
    uint16 lport    = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    uint8  loop_chan_dp[2][2] = {{114, 116}, {242, 244}};
    uint8  idx;

    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);

        /* validate used network channel */
        SYS_CONDITION_CONTINUE((!port_attr) || (port_attr->port_type == SYS_DMPS_RSV_PORT));
        /* validate misc channel */
        SYS_CONDITION_CONTINUE((port_attr->port_type != SYS_DMPS_NETWORK_PORT) && (port_attr->chan_id == SYS_TMM_USELESS_ID8));
        /*dp filter*/
        SYS_CONDITION_CONTINUE(dp_id != SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id));

        /*loop chan 114 & 116*/
        if(loop_chan_dp[dp_id][0] == port_attr->chan_id)
        {
            for(idx = 0; idx < 2; idx++)
            {
                CTC_ERROR_RETURN(_sys_tmm_datapath_set_bufretrv_credit(lchip, loop_chan_dp[dp_id][idx], CTC_PORT_SPEED_200G));
            }
        }
        else
        {
            CTC_ERROR_RETURN(_sys_tmm_datapath_set_bufretrv_credit(lchip, port_attr->chan_id, port_attr->speed_mode));
        }
    }

    _sys_tmm_datapath_set_bufretrv_wrr_weight(lchip, dp_id);
    
    return CTC_E_NONE;
}
#endif


uint32
 _sys_tmm_datapath_epe_speed_to_credit(uint16 speed)
{
    uint16 i = 0;
    const uint16 line_num = 9;
                              /*<   10, 10, 25, 40, 50, 100, 200, 400*/
    const uint16 speed_lines[] = {0, 1, 10, 25, 40, 50, 100, 200, 400};
    const uint32 credits[]     = {0, 4,  6, 10, 12, 20,  30,  40,  80};   
    
    while((i < line_num) && (speed > speed_lines[i]))
    {
        i++;
    }
    SYS_CONDITION_RETURN((i >= line_num), 0);

    return credits[i];
}

int32
_sys_tmm_datapath_set_epe_credit(uint8 lchip, uint8 alloc_type, sys_datapath_lport_attr_t* port_attr)
{    
    uint32  index        = 0;
    uint32  cmd          = 0;
    uint32  credit       = 0;
    uint16  speed        = 0;
    uint32  dp_id        = 0;
    uint32  step         = 0;
    uint32  txqm_mac_id  = 0;
    uint32  tbl_id       = EpeScheduleToNet0CreditConfigRa_t;
    uint32  offset       = EpeScheduleToNet1CreditConfigRa_t - EpeScheduleToNet0CreditConfigRa_t;
    EpeScheduleToNet0CreditConfigRa_m epe_credit  = {{0}};

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    SYS_CONDITION_RETURN(SYS_DMPS_NETWORK_PORT != port_attr->port_type, CTC_E_NONE);

    SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);
    if (SYS_DMPS_INACTIVE_NETWORK_PORT == port_attr->port_type)
    {
        speed = 0;
    }

    credit = _sys_tmm_datapath_epe_speed_to_credit(speed);

    dp_id = SYS_TMM_GET_DP_ID_FROM_MACID(port_attr->mac_id);
    if(SYS_ALLOC_XPIPE_PMAC == alloc_type)
    {
        txqm_mac_id = TXQM_INNER_MAC_ID(port_attr->pmac_id);
    }
    else
    {
        txqm_mac_id = TXQM_INNER_MAC_ID(port_attr->mac_id);
    }
    index = DRV_INS(dp_id, txqm_mac_id);
    step = SYS_TMM_GET_TXQM_PER_DP(port_attr->txqm_id);
    tbl_id += step * offset;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &epe_credit);

    DRV_IOW_FIELD_NZ(lchip, tbl_id, EpeScheduleToNet0CreditConfigRa_cfgCreditValue_f, &credit, &epe_credit, 
        dp_id, txqm_mac_id);
    
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &epe_credit);

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_epe_misc_port_id_cfg(uint8 lchip, uint8 dp_id)
{
    uint32  index      = 0;
    uint32  cmd        = 0;
    uint32  value      = 0;
    EpeSchedulePortIdCfg_m epe_port;
    
    index = DRV_INS(dp_id, 0);
    cmd = DRV_IOR(EpeSchedulePortIdCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &epe_port));
    value = 0xa2; //CPUMAC 0: 162
    DRV_IOW_FIELD_NZ(lchip, EpeSchedulePortIdCfg_t, EpeSchedulePortIdCfg_cfgCpuMac0PortId_f, &value, &epe_port, dp_id, 0);
    value = 0xa3; //CPUMAC 1: 163
    DRV_IOW_FIELD_NZ(lchip, EpeSchedulePortIdCfg_t, EpeSchedulePortIdCfg_cfgCpuMac1PortId_f, &value, &epe_port, dp_id, 0);
    value = 0xa0; //DMA 0: 160
    DRV_IOW_FIELD_NZ(lchip, EpeSchedulePortIdCfg_t, EpeSchedulePortIdCfg_cfgDma0PortId_f,    &value, &epe_port, dp_id, 0);
    value = 0xa1; //DMA 1: 161
    DRV_IOW_FIELD_NZ(lchip, EpeSchedulePortIdCfg_t, EpeSchedulePortIdCfg_cfgDma1PortId_f,    &value, &epe_port, dp_id, 0);
    
    cmd = DRV_IOW(EpeSchedulePortIdCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &epe_port));

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_epe_extra_cfg(uint8 lchip)
{
    uint32  index      = 0;
    uint32  cmd        = 0;
    uint32  value      = 0;
    EpeHdrEditExtraCreditConfig_m epe_ext;

    /*write EpeHdrEditExtraCreditConfig.extraCreditUplink 2 to solve stacking port queue blocked*/
    cmd = DRV_IOR(EpeHdrEditExtraCreditConfig_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &epe_ext));
    value = 2;
    DRV_IOW_FIELD(lchip, EpeHdrEditExtraCreditConfig_t, EpeHdrEditExtraCreditConfig_extraCreditUplink_f, &value, &epe_ext);
    cmd = DRV_IOW(EpeHdrEditExtraCreditConfig_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &epe_ext));

    return CTC_E_NONE;
}

/*misc port using special mac id*/
int32
_sys_tmm_datapath_misc_port_get_dp_macid_by_chanid(uint8 lchip, uint8 dp_id, uint8 dp_chan_id, uint32* p_dp_mac_id)
{
    uint8  i;
    uint16 misc_dp_chan_2_macid[9][2] = 
    {  /*misc chan    mac id*/
        {112,         162}, //cpumac
        {113,         163}, //cpumac
        {114,         165}, //MCHIP_CAP(SYS_CAP_CHANID_LOO0)
        {115,         166}, //MCHIP_CAP(SYS_CAP_CHANID_LOO1)
        {116,         167}, //MCHIP_CAP(SYS_CAP_CHANID_LOO2)
        {117,         168}, //MCHIP_CAP(SYS_CAP_CHANID_LOO3)
        {118,         164}, //oam
        {120,         160}, //DMA
        {121,         161}, //DMA
    };

    if(0 == dp_id)
    {
        misc_dp_chan_2_macid[0][0] = SYS_TMM_GET_CHANN_PER_DP(p_usw_datapath_master[lchip]->cpumac_map[0].chan_id);
        misc_dp_chan_2_macid[1][0] = SYS_TMM_GET_CHANN_PER_DP(p_usw_datapath_master[lchip]->cpumac_map[1].chan_id);
    }
    else
    {
        misc_dp_chan_2_macid[0][0] = SYS_TMM_GET_CHANN_PER_DP(p_usw_datapath_master[lchip]->cpumac_map[2].chan_id);
        misc_dp_chan_2_macid[1][0] = SYS_TMM_GET_CHANN_PER_DP(p_usw_datapath_master[lchip]->cpumac_map[3].chan_id);
    }

    for(i = 0; i < 9; i++)
    {
        if(dp_chan_id == misc_dp_chan_2_macid[i][0])
        {
            SYS_USW_VALID_PTR_WRITE(p_dp_mac_id, misc_dp_chan_2_macid[i][1]);
            return CTC_E_NONE;
        }
    }
    
    SYS_USW_VALID_PTR_WRITE(p_dp_mac_id, SYS_TMM_USELESS_ID16);
    return CTC_E_INVALID_PARAM;
}

int32
_sys_tmm_datapath_epehdr_chanportmap(uint8 lchip, uint16 lport, uint8 chan)
{
    uint32  cmd        = 0;
    uint32  val_u32    = lport;

    cmd = DRV_IOW(EpeHeaderAdjustPhyPortMap_t, EpeHeaderAdjustPhyPortMap_localPhyPort_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan, cmd, &val_u32));

    return CTC_E_NONE;
}

int32 
_sys_tmm_datapath_epe_port_chan_map(uint8 lchip, uint8 dp_id, uint32 dp_mac_id, uint32  dp_chan_id)
{
    uint32  index      = 0;
    uint32  cmd        = 0;
    EpeSchedulePortToChanRa_m port_to_chan = {{0}};
    EpeScheduleChanToPortRa_m chan_to_port = {{0}};
    /* port to chan mapping*/
    index = DRV_INS(dp_id, dp_mac_id);
    cmd = DRV_IOR(EpeSchedulePortToChanRa_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &port_to_chan);
    DRV_IOW_FIELD_NZ(lchip, EpeSchedulePortToChanRa_t, EpeSchedulePortToChanRa_internalChanId_f, 
        &dp_chan_id, &port_to_chan, dp_id, dp_mac_id);
    cmd = DRV_IOW(EpeSchedulePortToChanRa_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &port_to_chan);
    
    /* chan to port mapping*/
    index = DRV_INS(dp_id, dp_chan_id);
    cmd = DRV_IOR(EpeScheduleChanToPortRa_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &chan_to_port);
    DRV_IOW_FIELD_NZ(lchip, EpeScheduleChanToPortRa_t, EpeScheduleChanToPortRa_physicalPortId_f, 
        &dp_mac_id, &chan_to_port, dp_id, dp_chan_id);
    cmd = DRV_IOW(EpeScheduleChanToPortRa_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &chan_to_port);

    return CTC_E_NONE;
}

int32 
_sys_tmm_datapath_set_epe_port_chan_mapping(uint8 lchip, uint8 alloc_type, 
                                                     sys_datapath_lport_attr_t* port_attr)
{
    uint8   dp_id      = SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id);
    uint32  dp_mac_id;
    uint32  dp_chan_id;
    uint16  lport      = sys_usw_datapath_get_lport_with_mac(lchip, port_attr->mac_id);

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    /*20201118 update  add EpeHeaderAdjustPhyPortMap config*/
    if(SYS_COMMON_USELESS_MAC != lport)
    {
        CTC_ERROR_RETURN(_sys_tmm_datapath_epehdr_chanportmap(lchip, lport, port_attr->chan_id));
    }

    if ((SYS_DMPS_NETWORK_PORT != port_attr->port_type) && (SYS_DMPS_INACTIVE_NETWORK_PORT != port_attr->port_type))
    {
        dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(port_attr->chan_id);
        _sys_tmm_datapath_misc_port_get_dp_macid_by_chanid(lchip, dp_id, dp_chan_id, &dp_mac_id);
        SYS_CONDITION_RETURN(SYS_TMM_USELESS_ID16 == dp_mac_id, CTC_E_NONE);
    }
    else
    {
        if(SYS_ALLOC_XPIPE_PMAC == alloc_type)
        {
            dp_mac_id  = SYS_TMM_GET_MACID_PER_DP(port_attr->pmac_id);
            dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(port_attr->pmac_chanid);
        }
        else
        {
            dp_mac_id  = SYS_TMM_GET_MACID_PER_DP(port_attr->mac_id);
            dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(port_attr->chan_id);
        }
    }

    CTC_ERROR_RETURN(_sys_tmm_datapath_epe_port_chan_map(lchip, dp_id, dp_mac_id, dp_chan_id));

    /*chan 120 is saved in port_attr, but chan 121 not (because they belong to one lport), so 121 need a special operation*/
    if(MCHIP_CAP(SYS_CAP_CHANID_DMA_RX0) == port_attr->chan_id)
    {
        _sys_tmm_datapath_misc_port_get_dp_macid_by_chanid(lchip, dp_id, MCHIP_CAP(SYS_CAP_CHANID_DMA_RX1), &dp_mac_id);
        dp_chan_id = MCHIP_CAP(SYS_CAP_CHANID_DMA_RX1);

        CTC_ERROR_RETURN(_sys_tmm_datapath_epe_port_chan_map(lchip, dp_id, dp_mac_id, dp_chan_id));
    }
    /*loop chan 114~117*/
    if(MCHIP_CAP(SYS_CAP_CHANID_LOO0) == port_attr->chan_id)
    {
        _sys_tmm_datapath_misc_port_get_dp_macid_by_chanid(lchip, dp_id, MCHIP_CAP(SYS_CAP_CHANID_LOO2), &dp_mac_id);
        /*116 in dp 0*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_epe_port_chan_map(lchip, 0, dp_mac_id, MCHIP_CAP(SYS_CAP_CHANID_LOO2)));
    }
    else if ((MCHIP_CAP(SYS_CAP_CHANID_LOO0) + MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM)) == port_attr->chan_id)
    {
        _sys_tmm_datapath_misc_port_get_dp_macid_by_chanid(lchip, dp_id, MCHIP_CAP(SYS_CAP_CHANID_LOO2), &dp_mac_id);
        /*117 in dp 1*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_epe_port_chan_map(lchip, 1, dp_mac_id, MCHIP_CAP(SYS_CAP_CHANID_LOO2)));
    }

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

#if (SDB_MEM_MODEL != SDB_MODE)
STATIC int32
_sys_tmm_datapath_epe_init(uint8 lchip, uint8 dp_id)
{
    uint16  lport       = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    
    /* map chan to port & port to chan */ 
    /* only configure phy port */
    for(lport = 0; lport <MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, lport, &port_attr));
        SYS_CONDITION_CONTINUE(port_attr->port_type == SYS_DMPS_RSV_PORT);
        /*dp filter*/
        SYS_CONDITION_CONTINUE(dp_id != SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id));
        /* need to configure EpeHeaderAdjustPhyMac_t? */
        /*config chan-mac mapping network & misc*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_epe_port_chan_mapping(lchip, SYS_ALLOC_NORMAL, port_attr));

        CTC_ERROR_RETURN(_sys_tmm_datapath_set_epe_credit(lchip, SYS_ALLOC_NORMAL, port_attr));
    }
    
    CTC_ERROR_RETURN(_sys_tmm_datapath_epe_xg_lg_enable(lchip, dp_id));
    
    CTC_ERROR_RETURN(_sys_tmm_datapath_set_epe_wrr_weight(lchip, dp_id));

    CTC_ERROR_RETURN(sys_tmm_datapath_epe_misc_port_id_cfg(lchip, dp_id));

    CTC_ERROR_RETURN(sys_tmm_datapath_epe_extra_cfg(lchip));

    return CTC_E_NONE;
}
#endif

uint32
_sys_tmm_nettx_speed_to_credit(uint16 speed)
{
    uint32 credit = 0;
    credit = 
        (speed>=400) ? 50 :
        (speed>=200) ? 50 :
        (speed>=100) ? 25 :
        (speed>=40)  ? 12 : 
        (speed>=20)  ? 10 :
        (speed>=15)  ? 8 :
        (speed>=10)  ? 6 :
        (speed>=5)   ? 5 :
        (speed>=1)   ? 3 : 0; //5->3 for 32*qsgmii+8*25g nettx sum check

    return credit;
}


int32
_sys_tmm_datapath_set_nettx_credit(uint8 lchip, uint8 alloc_type, sys_datapath_lport_attr_t* port_attr)
{
    uint32  dp_id     = 0;
    uint32  dp_mac_id = 0;
    uint32  cmd       = 0;
    uint32  index     = 0; 
    uint16  speed     = 0;
    uint32  credit    = 0;
    NetTxCreditThrd_m credit_cfg = {{0}};

    SYS_CONDITION_RETURN(SYS_TMM_MAX_MAC_NUM <= port_attr->mac_id, CTC_E_NONE);

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    dp_id = SYS_TMM_GET_DP_ID_FROM_MACID(port_attr->mac_id);
    if(SYS_ALLOC_XPIPE_PMAC == alloc_type)
    {
        dp_mac_id = SYS_TMM_GET_MACID_PER_DP(port_attr->pmac_id);
    }
    else
    {
        dp_mac_id = SYS_TMM_GET_MACID_PER_DP(port_attr->mac_id);
    }

    SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);
    if (SYS_DMPS_INACTIVE_NETWORK_PORT == port_attr->port_type)
    {
        speed = 0;
    }
    credit = _sys_tmm_nettx_speed_to_credit(speed);

    index = DRV_INS(dp_id, dp_mac_id); 

    cmd = DRV_IOR(NetTxCreditThrd_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &credit_cfg);
    
    DRV_IOW_FIELD_NZ(lchip, NetTxCreditThrd_t, NetTxCreditThrd_data_f, &credit, &credit_cfg, dp_id, dp_mac_id);
    cmd = DRV_IOW(NetTxCreditThrd_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, index, cmd, &credit_cfg);

    if ((2 == port_attr->client_bind_num) && (SYS_TMM_USELESS_ID16 != port_attr->mac_id_aps))
    {
        dp_mac_id = SYS_TMM_GET_MACID_PER_DP(port_attr->mac_id_aps);
        index = DRV_INS(dp_id, dp_mac_id);

        cmd = DRV_IOR(NetTxCreditThrd_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, index, cmd, &credit_cfg);

        credit = 0xff;
        DRV_IOW_FIELD_NZ(lchip, NetTxCreditThrd_t, NetTxCreditThrd_data_f, &credit, &credit_cfg, dp_id, dp_mac_id);
        cmd = DRV_IOW(NetTxCreditThrd_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, index, cmd, &credit_cfg);
    }

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}

/*calculate total network ports bandwidth in dp*/
uint32
_sys_tmm_datapath_get_sum_of_dp_network(uint8 lchip, uint8 dp_id)
{
    uint16  lport              = 0;
    uint16  speed              = 0;
    uint32  total_bw           = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(!port_attr || port_attr->port_type != SYS_DMPS_NETWORK_PORT);
        /*dp filter*/
        SYS_CONDITION_CONTINUE(dp_id != SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id));
        
        SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);        
        total_bw += speed;

        /*xpipe pmac*/
        SYS_CONDITION_CONTINUE(CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en);
        total_bw += speed;
    }
    return total_bw;
}

uint8
_sys_tmm_datapath_judge_nettx_longbufmode(uint8 lchip, uint8 dp_id, uint32 total_bw_given)
{
    uint32  total_bw           = 0;
    uint8   longbufmode_flag   = FALSE;

    if(500 == sys_usw_datapath_get_core_clock(lchip, 0))
    {
        total_bw = (SYS_TMM_USELESS_ID32 == total_bw_given) ? _sys_tmm_datapath_get_sum_of_dp_network(lchip, dp_id) : 
            total_bw_given;
        if(600 <= total_bw)
        {
            longbufmode_flag = TRUE;
        }
    }

    return longbufmode_flag;
}

int32
_sys_tmm_datapath_set_dp_nettx_txthrd(uint8 lchip, uint8 dp_id)
{
    uint32  cmd                = 0;
    uint32  entry_id           = 0;
    uint16  lport              = 0;
    uint16  speed              = 0;
    uint32  guarantee_thrd_val = 0;
    uint32  dp_mac_id          = 0;
    uint32  total_bw           = 0;
    uint8   longbufmode_flag   = FALSE;
    sys_datapath_lport_attr_t* port_attr = NULL;
    NetTxTxThrdCfg_m           tx_thrd;

    /*calculate total bandwidth in dp*/
    total_bw         = _sys_tmm_datapath_get_sum_of_dp_network(lchip, dp_id);
    longbufmode_flag = _sys_tmm_datapath_judge_nettx_longbufmode(lchip, dp_id, total_bw);

    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(!port_attr || port_attr->port_type != SYS_DMPS_NETWORK_PORT);
        /*dp filter*/
        SYS_CONDITION_CONTINUE(dp_id != SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id));

        dp_mac_id = SYS_TMM_GET_MACID_PER_DP(port_attr->mac_id);
        /* default value */
        guarantee_thrd_val = 2;

        SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);
        if(total_bw > 1200)
        {
            guarantee_thrd_val = 3;
        }
        if(speed < 25)
        {
            guarantee_thrd_val = 3;
        }

        if(longbufmode_flag)
        {
            guarantee_thrd_val += 2;
        }
        
        entry_id = DRV_INS(dp_id, dp_mac_id);
        cmd = DRV_IOR(NetTxTxThrdCfg_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &tx_thrd);

        DRV_IOW_FIELD_NZ(lchip, NetTxTxThrdCfg_t, NetTxTxThrdCfg_guaranteeTxThrd_f, &guarantee_thrd_val, &tx_thrd, dp_id, dp_mac_id);

        cmd = DRV_IOW(NetTxTxThrdCfg_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &tx_thrd);

        /*xpipe pmac*/
        SYS_CONDITION_CONTINUE((CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en) || (CTC_PORT_XPIPE_TYPE_6 == port_attr->xpipe_en));

        dp_mac_id = SYS_TMM_GET_MACID_PER_DP(port_attr->pmac_id);

        entry_id = DRV_INS(dp_id, dp_mac_id);
        cmd = DRV_IOR(NetTxTxThrdCfg_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &tx_thrd);

        DRV_IOW_FIELD_NZ(lchip, NetTxTxThrdCfg_t, NetTxTxThrdCfg_guaranteeTxThrd_f, &guarantee_thrd_val, &tx_thrd, dp_id, dp_mac_id);

        cmd = DRV_IOW(NetTxTxThrdCfg_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &tx_thrd);
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_nettx_timer_en(uint8 lchip, sys_datapath_lport_attr_t* port_attr, uint8 alloc_type)
{
    uint16 mac_id           = 0;
    uint8  UINT32_BIT_LEN   = 32;
    uint8  dp_txqm_id       = 0;
    uint8  inner_mac_id     = 0;
    uint8  dp_id            = 0;
    uint16 dp_mac_id        = 0;
    uint16 speed            = 0;
    uint32 cmd              = 0;
    uint32 field_id         = 0;
    uint32 tmp_val32        = 0x1;
    uint32 entry_id         = 0;
    uint32 timer_enable[2]  = {0x0, 0x0};
    uint8  longbufmode_flag = FALSE;
    NetTxTimerEnCtl_m       enable_cfg;
    NetTxTxTimerThrdCfg_m   tx_timer_thrd;
    NetTxTxThrdCfg_m        tx_thrd;

    SYS_CONDITION_RETURN(!port_attr || port_attr->port_type != SYS_DMPS_NETWORK_PORT, CTC_E_NONE);
    SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);

    mac_id = (SYS_ALLOC_NORMAL == alloc_type) ? port_attr->mac_id : port_attr->pmac_id;

    dp_txqm_id   = SYS_TMM_GET_TXQM_BY_MACID(mac_id) % SYS_TMM_TXQM_NUM_PER_DP;
    inner_mac_id = SYS_TMM_GET_MACID_PER_TXQM(mac_id);
    dp_id        = SYS_TMM_GET_DP_ID_FROM_MACID(mac_id);
    dp_mac_id    = SYS_TMM_GET_MACID_PER_DP(mac_id);
    longbufmode_flag = _sys_tmm_datapath_judge_nettx_longbufmode(lchip, dp_id, SYS_TMM_USELESS_ID32);

    /*1. Timer en*/
    entry_id = DRV_INS(dp_id, 0);
    cmd = DRV_IOR(NetTxTimerEnCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &enable_cfg));

    field_id = NetTxTimerEnCtl_txTimerEn0_f + (NetTxTimerEnCtl_txTimerEn1_f - NetTxTimerEnCtl_txTimerEn0_f)*dp_txqm_id;
    DRV_IOR_FIELD(lchip, NetTxTimerEnCtl_t, field_id, timer_enable, &enable_cfg);

    tmp_val32 = tmp_val32 << (inner_mac_id % UINT32_BIT_LEN);
    if(longbufmode_flag)
    {
        timer_enable[inner_mac_id / UINT32_BIT_LEN] &= (~tmp_val32);
    }
    else
    {
        /*when then speed rate less than or equal to 10G, write 0*/
        if(speed <= 10)
        {
             timer_enable[inner_mac_id / UINT32_BIT_LEN] &= (~tmp_val32);
        }
        /*when then speed rate greater than 10G, write 1*/
        else
        {
            timer_enable[inner_mac_id / UINT32_BIT_LEN] |= tmp_val32;
        }
    }

    DRV_IOW_FIELD(lchip, NetTxTimerEnCtl_t, field_id, timer_enable, &enable_cfg);
    cmd = DRV_IOW(NetTxTimerEnCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &enable_cfg));

    /*2. Timer thrd*/
    entry_id = DRV_INS(dp_id, dp_mac_id);
    cmd = DRV_IOR(NetTxTxTimerThrdCfg_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &tx_timer_thrd);

    tmp_val32 = speed >= 300 ? 80 :
                speed >= 200 ? 14 :
                speed >= 100 ? 32 :
                speed >= 50  ? 64 :
                speed >= 40  ? 64 :
                speed >= 25  ? 129 :
                speed >= 10  ? 140 :
                speed >= 1   ? 200 : 0;
    DRV_IOW_FIELD_NZ(lchip, NetTxTxTimerThrdCfg_t, NetTxTxTimerThrdCfg_txTimerThrd_f, &tmp_val32, &tx_timer_thrd, dp_id, dp_mac_id);

    cmd = DRV_IOW(NetTxTxTimerThrdCfg_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &tx_timer_thrd);

    /*3. Tx thrd*/
    cmd = DRV_IOR(NetTxTxThrdCfg_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &tx_thrd);

    if(longbufmode_flag)
    {
        tmp_val32 = speed >= 300 ? 15 : 
                    speed >= 25  ? 10 :
                    speed >= 10  ? 6  : 4;
    }
    else
    {
        tmp_val32 = speed >= 300 ? 15 : 
                    speed >= 100 ? 7  :
                    speed >= 10  ? 5  : 4;
    }
    DRV_IOW_FIELD_NZ(lchip, NetTxTxThrdCfg_t, NetTxTxThrdCfg_txthrd_f, &tmp_val32, &tx_thrd, dp_id, dp_mac_id);

    cmd = DRV_IOW(NetTxTxThrdCfg_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &tx_thrd);

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_nettx_switch_to_ready(uint8 lchip, uint8 dp_id)
{
    uint32 cmd              = 0;
    uint32 entry_id         = 0;
    uint32 tmp_val32        = 0;
    NetTxMiscCtl_m misc_ctl = {{0}};

    entry_id = DRV_INS(dp_id, 0);
    
    cmd = DRV_IOR(NetTxMiscCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &misc_ctl));
    
    tmp_val32 = 1;
    DRV_IOW_FIELD_NZ(lchip, NetTxMiscCtl_t, NetTxMiscCtl_netTxReady_f, &tmp_val32, &misc_ctl, dp_id, 0);
    
    cmd = DRV_IOW(NetTxMiscCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, &misc_ctl));

    return CTC_E_NONE;
}

#if (SDB_MEM_MODEL != SDB_MODE)
STATIC uint32
_sys_tmm_datapath_nettx_init(uint8 lchip, uint8 dp_id)
{    
    uint16  lport       = 0;
    uint16  total_bw    = 0;
    uint16  speed       = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(!port_attr || port_attr->port_type != SYS_DMPS_NETWORK_PORT);
        /*dp filter*/
        SYS_CONDITION_CONTINUE(dp_id != SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id));
        
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_nettx_credit(lchip, SYS_ALLOC_NORMAL, port_attr));

        CTC_ERROR_RETURN(_sys_tmm_datapath_nettx_timer_en(lchip, port_attr, SYS_ALLOC_NORMAL));

        SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);        
        total_bw += speed;
    }

    CTC_ERROR_RETURN(_sys_tmm_datapath_set_dp_nettx_txthrd(lchip, dp_id));

    CTC_ERROR_RETURN(_sys_tmm_datapath_nettx_switch_to_ready(lchip, dp_id));

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}
#endif

int32
_sys_tmm_datapath_set_extra_cfg(uint8 lchip, uint8 dp_id)
{
    uint32 cmd           = 0;
    uint32 val_32        = 0;
    uint32 entry_id      = 0;
    uint32 dp_chan_id    = 0;
    uint32 chan_id       = 0;
    DsChannelizeMode_m   mode;
    BrPrioritySelect_m   priority_sel;
    BufStoreProcFifoCtl_m bs_ctl;

#ifdef PCS_IMG
    IpeShellCreditCtl_m  ipe_ctl;

    /*clear IpeShellCreditCtl*/
    entry_id = DRV_INS(0, 0);
    cmd = DRV_IOR(IpeShellCreditCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &ipe_ctl);

    val_32 = 0xf;
    DRV_IOW_FIELD_NZ(lchip, IpeShellCreditCtl_t, IpeShellCreditCtl_bsIpeFwdCreditThrd_f, &val_32, &ipe_ctl, 0, 0);

    val_32 = 0xff;
    DRV_IOW_FIELD_NZ(lchip, IpeShellCreditCtl_t, IpeShellCreditCtl_hdrGenFifoCreditThrd_f, &val_32, &ipe_ctl, 0, 0);

    val_32 = 0x10;
    DRV_IOW_FIELD_NZ(lchip, IpeShellCreditCtl_t, IpeShellCreditCtl_ipeShellInputCreditThrd_f, &val_32, &ipe_ctl, 0, 0);
         
    val_32 = 0xffff;
    DRV_IOW_FIELD_NZ(lchip, IpeShellCreditCtl_t, IpeShellCreditCtl_macDecEopStallThrd_f, &val_32, &ipe_ctl, 0, 0);
    
    cmd = DRV_IOW(IpeShellCreditCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &ipe_ctl);

    /* bug fixed: 12 * 100G R4          underrun */
    EpeShellDestChanDelayCfgRa_m epe_shell_delay;

    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        chan_id  = dp_id*SYS_TMM_CHANNEL_NUM_PER_DP + dp_chan_id;
        entry_id = DRV_INS(0, chan_id);     // only one instance
        cmd = DRV_IOR(EpeShellDestChanDelayCfgRa_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &epe_shell_delay);
    
        val_32 = (((chan_id*3+7)*5+ (chan_id*chan_id) +1)%21 ) + 80 ;
        DRV_IOW_FIELD_NZ(lchip, EpeShellDestChanDelayCfgRa_t, EpeShellDestChanDelayCfgRa_cfgDelayValue_f, 
            &val_32, &epe_shell_delay, 0, chan_id);
    
        cmd = DRV_IOW(EpeShellDestChanDelayCfgRa_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &epe_shell_delay);
    }

    /*clear QMgrShellChanWrEnCtl*/
    uint32 data[8] = {0};       // 256 bit
    entry_id = DRV_INS(0, 0);   // only one instance

    cmd = DRV_IOW(QMgrShellChanWrEnCtl_t, QMgrShellChanWrEnCtl_chanWrEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, entry_id, cmd, data));
#endif

    /*config max len*/
    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        entry_id = DRV_INS(dp_id, dp_chan_id); // every DP has one instance
        cmd = DRV_IOR(DsChannelizeMode_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &mode);

        val_32 = 0x3FFF;
        DRV_IOW_FIELD_NZ(lchip, DsChannelizeMode_t, DsChannelizeMode_portMaxLen_f, &val_32, &mode, dp_id, dp_chan_id);

        cmd = DRV_IOW(DsChannelizeMode_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &mode);
    }

    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        chan_id  = dp_id*SYS_TMM_CHANNEL_NUM_PER_DP + dp_chan_id;
        entry_id = DRV_INS(0, chan_id);     // only one instance
        cmd = DRV_IOR(BrPrioritySelect_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &priority_sel);
    
        val_32 = chan_id%2 + 1;
        DRV_IOW_FIELD_NZ(lchip, BrPrioritySelect_t, BrPrioritySelect_brPrioritySelect_f, &val_32, &priority_sel, 0, chan_id);
    
        cmd = DRV_IOW(BrPrioritySelect_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, entry_id, cmd, &priority_sel);
    }

    /*set BufStoreProcFifoCtl.bsIpeFreePtrFifoSlice0Dp0/1AEmptyThrd 38*/
    entry_id = DRV_INS(0, 0);
    cmd = DRV_IOR(BufStoreProcFifoCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &bs_ctl);
    val_32 = 38;
    DRV_IOW_FIELD_NZ(lchip, BufStoreProcFifoCtl_t, BufStoreProcFifoCtl_bsIpeFreePtrFifoSlice0Dp0AEmptyThrd_f + dp_id, &val_32, &bs_ctl, 0, 0);
    cmd = DRV_IOW(BufStoreProcFifoCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, entry_id, cmd, &bs_ctl);

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_ipe_chan2lport_init(uint8 lchip, uint8 dp)
{
    uint32 lport = 0;
    uint8  chan_id;
    uint8  dp_chan_id;

    /*ipe chan-lport map    only network & misc*/
    for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
    {
        SYS_CONDITION_CONTINUE(SYS_CHAN_LPORT_OCCUPY_RSV == p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp][dp_chan_id].occupy_flag);

        chan_id = dp*SYS_TMM_CHANNEL_NUM_PER_DP + dp_chan_id;
        lport = p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp][dp_chan_id].lport;
        CTC_ERROR_RETURN(_sys_tmm_datapath_ipehdr_chanportmap(lchip, lport, chan_id));
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_set_ipe_popslot(uint8 lchip, uint8 is_mode_cfg, ctc_port_bitmap_t port_bmp)
{
    uint32 cmd     = 0;
    uint32 idx0,  idx1;
    uint16 lport   = 0;
    uint8  dp_id   = 0;
    uint32 lv_id   = 0;
    uint32 lv_est  = 0;
    uint32 speed   = 0;
    uint32 ratio   = 0;
    uint32 factor  = 10000;
    uint32 val_u32 = 0;
    uint32 speed_sum[SYS_TMM_DP_NUM] = {0};
    uint32 level[17] = {
      /*DP1:DP0*/
      /*0:16    1:15    2:14    3:13    4:12    5:11    6:10    7:9*/
        0,      667,    1429,   2308,   3333,   4545,   6000,   7778, 
      /*8:8     9:7     10:6    11:5    12:4    13:3    14:2    15:1    16:0*/
        10000,  12857,  16667,  22000,  30000,  43333,  70000,  150000, 160000};
    uint32 slot[17] = {
      /*DP1:DP0*/
      /*0:16    1:15    2:14    3:13    4:12    5:11    6:10    7:9*/
        0x4444, 0x4444, 0x4444, 0x4444, 0x4444, 0x5444, 0x5454, 0x5554, 
      /*8:8     9:7     10:6    11:5    12:4    13:3    14:2    15:1    16:0*/
        0x5555, 0x5557, 0x5757, 0x5777, 0x7777, 0x7777, 0x7777, 0x7777, 0x7777};
    sys_datapath_lport_attr_t* port_attr = NULL;
    IpeHdrAdjReserved_m ipe_rsv;
    IpeHdrAdjInputFifoPopSlotCfg_m ipe_slt;

    /*1. sum dp bw*/
    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        SYS_CONDITION_CONTINUE(!port_attr || port_attr->port_type != SYS_DMPS_NETWORK_PORT);

        idx0 = lport / CTC_UINT32_BITS;
        idx1 = lport % CTC_UINT32_BITS;
        SYS_CONDITION_CONTINUE((!is_mode_cfg) && (CTC_IS_BIT_SET(port_bmp[idx0], idx1)));

        if(CTC_PORT_IF_FLEXE == port_attr->interface_type)
        {
            speed = port_attr->speed_value;
        }
        else
        {
            SYS_DATAPATH_MODE_TO_SPEED(port_attr->speed_mode, speed);
        }

        dp_id = SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id);

        speed_sum[dp_id] += speed;
    }

    /*2. get normalized ratio*/
    ratio = (speed_sum[0] == 0) ? (16 * factor) : (speed_sum[1] * factor / speed_sum[0]);

    /*3. judge level*/
    for(lv_id = 1; lv_id < 17; lv_id++)
    {
        SYS_CONDITION_BREAK((level[lv_id] >= ratio) && (level[lv_id-1] <= ratio));
    }
    lv_id = ((lv_id >= 17) ? 16 : lv_id);
    lv_est = ((ratio - level[lv_id-1]) > (level[lv_id] - ratio)) ? lv_id : (lv_id - 1);

    /*4. write slot bits*/
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "set_ipe_popslot: BW[%u %u], ratio %u, value 0x%04x\n", 
        speed_sum[0], speed_sum[1], ratio, slot[lv_est]);

    /*IpeHdrAdjReserved.reserved write 0 to enable*/
    val_u32 = 0;
    cmd = DRV_IOR(IpeHdrAdjReserved_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &ipe_rsv);
    DRV_IOW_FIELD_NZ(lchip, IpeHdrAdjReserved_t, IpeHdrAdjReserved_reserved_f, &val_u32, &ipe_rsv, 0, 0);
    cmd = DRV_IOW(IpeHdrAdjReserved_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &ipe_rsv);

    /*IpeHdrAdjInputFifoPopSlotCfg.inputFifoPopSlot*/
    val_u32 = slot[lv_est];
    cmd = DRV_IOR(IpeHdrAdjInputFifoPopSlotCfg_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &ipe_slt);
    DRV_IOW_FIELD_NZ(lchip, IpeHdrAdjInputFifoPopSlotCfg_t, IpeHdrAdjInputFifoPopSlotCfg_inputFifoPopSlot_f, &val_u32, &ipe_slt, 0, 0);
    cmd = DRV_IOW(IpeHdrAdjInputFifoPopSlotCfg_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &ipe_slt);

    return CTC_E_NONE;
}

/*loop-log mode config, default mode is 0. 
This option is valid only if subtype is B. */
int32
_sys_tmm_datapath_loop_log_mode_cfg(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
    uint32 write_tbl[11][3] = {
       /*table id                field                                               inst*/
        {NetRxWrrWeight_t,       NetRxWrrWeight_cfgSlotBitMapWeight_f,               DRV_INS(0, 0)}, /*0 NetRxWrrWeight.cfgSlotBitMapWeight              */              
        {NetRxWrrWeight_t,       NetRxWrrWeight_cfgSlotBitMapWeight_f,               DRV_INS(1, 0)}, /*1 NetRxWrrWeight.cfgSlotBitMapWeight              */              
        {HMacEngineReserved_t,   HMacEngineReserved_reserved_f,                      DRV_INS(0, 0)}, /*2 HMacEngineReserved.reserved                     */                     
        {EpeScheduleCreditCtl_t, EpeScheduleCreditCtl_toHMacIntf0ELogCreditThrd_f,   DRV_INS(0, 0)}, /*3 EpeScheduleCreditCtl.toHMacIntf0ELogCreditThrd  */  
        {EpeScheduleCreditCtl_t, EpeScheduleCreditCtl_toHMacIntf1ELogCreditThrd_f,   DRV_INS(0, 0)}, /*4 EpeScheduleCreditCtl.toHMacIntf1ELogCreditThrd  */  
        {EpeScheduleCreditCtl_t, EpeScheduleCreditCtl_toHMacIntf0ELoop0CreditThrd_f, DRV_INS(0, 0)}, /*5 EpeScheduleCreditCtl.toHMacIntf0ELoop0CreditThrd*/
        {EpeScheduleCreditCtl_t, EpeScheduleCreditCtl_toHMacIntf1ELoop0CreditThrd_f, DRV_INS(0, 0)}, /*6 EpeScheduleCreditCtl.toHMacIntf1ELoop0CreditThrd*/
        {EpeScheduleCreditCtl_t, EpeScheduleCreditCtl_toHMacIntf0ELogCreditThrd_f,   DRV_INS(1, 0)}, /*7 EpeScheduleCreditCtl.toHMacIntf0ELogCreditThrd  */  
        {EpeScheduleCreditCtl_t, EpeScheduleCreditCtl_toHMacIntf1ELogCreditThrd_f,   DRV_INS(1, 0)}, /*8 EpeScheduleCreditCtl.toHMacIntf1ELogCreditThrd  */  
        {EpeScheduleCreditCtl_t, EpeScheduleCreditCtl_toHMacIntf0ELoop0CreditThrd_f, DRV_INS(1, 0)}, /*9 EpeScheduleCreditCtl.toHMacIntf0ELoop0CreditThrd*/
        {EpeScheduleCreditCtl_t, EpeScheduleCreditCtl_toHMacIntf1ELoop0CreditThrd_f, DRV_INS(1, 0)}, /*10EpeScheduleCreditCtl.toHMacIntf1ELoop0CreditThrd*/
    };
    uint32 value[11][3] = {
       /*Loop>Log    Loop<Log    loop=log  */
        {0x55555555, 0x55555555, 0x55555555}, /*0 NetRxWrrWeight.cfgSlotBitMapWeight              */
        {0x55555555, 0x55555555, 0x55555555}, /*1 NetRxWrrWeight.cfgSlotBitMapWeight              */
        {0xffff,     0xffff,     0xffff    }, /*2 HMacEngineReserved.reserved                     */
        {7,          20,         12        }, /*3 EpeScheduleCreditCtl.toHMacIntf0ELogCreditThrd  */
        {7,          20,         12        }, /*4 EpeScheduleCreditCtl.toHMacIntf1ELogCreditThrd  */
        {17,         4,          12        }, /*5 EpeScheduleCreditCtl.toHMacIntf0ELoop0CreditThrd*/
        {17,         4,          12        }, /*6 EpeScheduleCreditCtl.toHMacIntf1ELoop0CreditThrd*/
        {8,          20,         12        }, /*7 EpeScheduleCreditCtl.toHMacIntf0ELogCreditThrd  */
        {8,          20,         12        }, /*8 EpeScheduleCreditCtl.toHMacIntf1ELogCreditThrd  */
        {16,         4,          12        }, /*9 EpeScheduleCreditCtl.toHMacIntf0ELoop0CreditThrd*/
        {16,         4,          12        }, /*10EpeScheduleCreditCtl.toHMacIntf1ELoop0CreditThrd*/
    };
    uint8  option     = (3 < p_datapath_cfg->loop_bandwidth) ? 0 : p_datapath_cfg->loop_bandwidth;
    uint32 cmd        = 0;
    uint32 val_str[4] = {0};
    uint8  item;

    SYS_CONDITION_RETURN((SYS_CHIP_SUB_VERSION_A == SYS_GET_CHIP_VERSION) || (3 == option), CTC_E_NONE);

    for(item = 0; item < 11; item++)
    {
        cmd = DRV_IOR(write_tbl[item][0], DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, write_tbl[item][2], cmd, &val_str);

        DRV_IOW_FIELD_NZ(lchip, write_tbl[item][0], write_tbl[item][1], &(value[item][option]), &val_str, write_tbl[item][2]>>24, 0);

        cmd = DRV_IOW(write_tbl[item][0], DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, write_tbl[item][2], cmd, &val_str);
    }

    return CTC_E_NONE;
}

#if (SDB_MEM_MODEL != SDB_MODE)
STATIC int32
_sys_tmm_datapath_dp_init(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
    uint8  dp_id;
    uint32 dp_txqm_id;
    uint32 txqm_id;
    uint8  hscs = 0; /*hs or cs, 0-hs, 1-cs*/
    uint8  hscs_idx = 0; /*hs or cs index, 0~3*/
    
    DP_DEBUG_FUNCTION_CALLED_PRINT();

    for(dp_id = 0; dp_id < SYS_TMM_DP_NUM; dp_id++)
    {
        SYS_CONDITION_CONTINUE((TRUE == p_usw_datapath_master[lchip]->hscs_down_flag[0][2*dp_id]) && 
                               (TRUE == p_usw_datapath_master[lchip]->hscs_down_flag[0][2*dp_id+1]) && 
                               (TRUE == p_usw_datapath_master[lchip]->hscs_down_flag[1][2*dp_id]) && 
                               (TRUE == p_usw_datapath_master[lchip]->hscs_down_flag[1][2*dp_id+1]));

        CTC_ERROR_RETURN(_sys_tmm_datapath_set_extra_cfg(lchip, dp_id));
    
        /*set Epe, NetRx, BufRetrv calendar*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_general_calendar(lchip, dp_id));

        /*set nettx calendar*/
        for(dp_txqm_id = 0; dp_txqm_id < SYS_TMM_TXQM_NUM_PER_DP; dp_txqm_id++)
        {
            txqm_id = dp_id * SYS_TMM_TXQM_NUM_PER_DP + dp_txqm_id;
            hscs    = SYS_TMM_IS_PCS_X16(txqm_id) ? 0 : 1;
            SYS_TMM_GET_PCSXIDX(txqm_id, hscs_idx);
            SYS_CONDITION_CONTINUE(TRUE == p_usw_datapath_master[lchip]->hscs_down_flag[hscs][hscs_idx]);
            CTC_ERROR_RETURN(_sys_tmm_datapath_set_nettx_calendar(lchip, dp_id, dp_txqm_id));
        }
        
        /*netrx: chan-mac mapping, wrr weight*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_netrx_init(lchip, dp_id));

        /*ipe chan-lport map    only network & misc*/
        CTC_ERROR_RETURN(sys_tmm_datapath_ipe_chan2lport_init(lchip, dp_id));

        /*bufretrv: credit, wrr weight*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_bufretrv_init(lchip, dp_id));

        /*epe: chan-mac mapping, credit, xglg en, wrr weight*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_epe_init(lchip, dp_id));

        /*nettx: credit, txthrd, timerEn, ready*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_nettx_init(lchip, dp_id));
    }

    /*qmgr init, total 2 dp: credit, xglg chan en, weight, start end*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_qmgr_init(lchip));

    CTC_ERROR_RETURN(_sys_tmm_datapath_loop_log_mode_cfg(lchip, p_datapath_cfg));

    CTC_ERROR_RETURN(_sys_tmm_datapath_set_ipe_popslot(lchip, TRUE, NULL));

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}


STATIC int32
_sys_tmm_datapath_sup_init(uint8 lchip)
{    
    uint32               cmd   = 0;
    uint32               value = 0;
    uint32               index = 0;
    uint32               ctcxs_id = 0;
    uint8                i     = 0;
    uint32               value_arr[2];
    uint32               sup_rst[2];
    uint32 write_st[SYS_MAC_MAX_STRUCT_WORD] = {0};

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);

    /*clear demuxLogErrValid*/
    cmd = DRV_IOR(DecodeMiscCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 1;
    DRV_IOW_FIELD(lchip, DecodeMiscCtl_t, DecodeMiscCtl_cfgDemuxInitEn_f, &value, write_st);
    cmd = DRV_IOW(DecodeMiscCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, DecodeMiscCtl_t, DecodeMiscCtl_cfgDemuxInitEn_f, &value, write_st);
    cmd = DRV_IOW(DecodeMiscCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    cmd = DRV_IOR(SupResetCtl_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, 0, cmd, &sup_rst);
    if (!GetSupResetCtl(V, resetDmaCtl_f, &sup_rst))
    {
        for (index=0;index <MCHIP_CAP(SYS_CAP_DMA_MAX_CHAN_ID); index++)
        {
            cmd = DRV_IOR(DmaStaticInfo_t, DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip, index, cmd, write_st);
            SetDmaStaticInfo(V, chanEn_f, write_st, 0);
            cmd = DRV_IOW(DmaStaticInfo_t, DRV_ENTRY_FLAG);
            DRV_IOCTL(lchip, index, cmd, write_st);
        }
        sal_task_sleep(2);
    }

    /*new add*/
    cmd = DRV_IOR(PcieResetCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, PcieResetCtl_t, PcieResetCtl_cfgSwitchReset_f, &value, write_st);
    cmd = DRV_IOW(PcieResetCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    /*do SupResetCtl reset*/
    sup_rst[0] = 0xffffffff;
    sup_rst[1] = 0xffffffff;
    if (sys_usw_chip_get_reset_hw_en(lchip))
    {
        SetSupResetCtl(V,cfgRstEcpuIntf_f, sup_rst, 0);/* reset ECPU in sys_usw_eunit_init */
        SetSupResetCtl(V,cfgRstScpuIntf_f, sup_rst, 0);/* reset SCPU in sys_usw_eunit_init */
    }
    cmd = DRV_IOW(SupResetCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &sup_rst));
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "write address 0x00051070 0xffffffff\n");
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "write address 0x00051074 0xf\n");
    sal_task_sleep(1);
    sup_rst[0] = 0;
    sup_rst[1] = 0;
    cmd = DRV_IOW(SupResetCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &sup_rst));
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "write address 0x00051070 0x0\n");
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "write address 0x00051074 0x0\n");

    /* PcieReg.txt */
    cmd = DRV_IOR(SupRegCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 1;
    DRV_IOW_FIELD(lchip, SupRegCtl_t, SupRegCtl_regReqCrossEn_f, &value, write_st);
    cmd = DRV_IOW(SupRegCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    /*Open clock enable*/
    cmd = DRV_IOR(SupEnClk_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0xffff;
    DRV_IOW_FIELD(lchip, SupEnClk_t, SupEnClk_cfgEnClkVec_f, &value, write_st);
    cmd = DRV_IOW(SupEnClk_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    cmd = DRV_IOR(SupDskCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, SupDskCfg_t, SupDskCfg_cfgResetClkHssAnLtRefDiv_f, &value, write_st);
    DRV_IOW_FIELD(lchip, SupDskCfg_t, SupDskCfg_cfgResetClkHssRegAccDiv_f,  &value, write_st);
    DRV_IOW_FIELD(lchip, SupDskCfg_t, SupDskCfg_cfgResetClkLedDiv_f,        &value, write_st);
    DRV_IOW_FIELD(lchip, SupDskCfg_t, SupDskCfg_cfgResetClkMdioADiv_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, SupDskCfg_t, SupDskCfg_cfgResetClkMdioBDiv_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, SupDskCfg_t, SupDskCfg_cfgResetClkMdioCDiv_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, SupDskCfg_t, SupDskCfg_cfgResetClkMdioDDiv_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, SupDskCfg_t, SupDskCfg_cfgResetClkMiscADiv_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, SupDskCfg_t, SupDskCfg_cfgResetClkOobFcTxDiv_f,    &value, write_st);
    DRV_IOW_FIELD(lchip, SupDskCfg_t, SupDskCfg_cfgResetClkTodDiv_f,        &value, write_st);
    cmd = DRV_IOW(SupDskCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    cmd = DRV_IOR(RefDivOamTokenUpd_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivOamTokenUpd_t, RefDivOamTokenUpd_cfgResetDivOamTokenUpdPulse_f,  &value, write_st);
    cmd = DRV_IOW(RefDivOamTokenUpd_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    /*Release Reset*/
    for (i = 0; i < 2; i++)
    {
        cmd = DRV_IOR(CtcDpRxCtlReset_t, DRV_ENTRY_FLAG);
        index = DRV_INS(i, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
        value = 0;
        DRV_IOW_FIELD_NZ(lchip, CtcDpRxCtlReset_t, CtcDpRxCtlReset_resetCoreMacSecDec_f, &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcDpRxCtlReset_t, CtcDpRxCtlReset_resetCoreNetRx_f,     &value, write_st, i, 0);
        cmd = DRV_IOW(CtcDpRxCtlReset_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
    }

    /*CtcIpeRxCtlReset*/
    cmd = DRV_IOR(CtcIpeRxCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreEfd_f,                &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreIpeHdrAdj_f,          &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreIpeIntfMap_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreIpeLkupMgrTop_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreIpePktProc_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreOamHash_f,            &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreParser0Ipe_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreParser1Ipe_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreSclEngine_f,          &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreSvcPolicing_f,        &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreProgramAclTcam_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreProgramAclLtidTcam_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeRxCtlReset_t, CtcIpeRxCtlReset_resetCoreIpeAcl_f,             &value, write_st);
    cmd = DRV_IOW(CtcIpeRxCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    /*CtcBsrCtlReset*/
    cmd = DRV_IOR(CtcBsrCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, CtcBsrCtlReset_t, CtcBsrCtlReset_resetCoreBufRetrvShare_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcBsrCtlReset_t, CtcBsrCtlReset_resetCoreBufRetrvSlice0Dp0_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CtcBsrCtlReset_t, CtcBsrCtlReset_resetCoreBufRetrvSlice0Dp1_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CtcBsrCtlReset_t, CtcBsrCtlReset_resetCoreBufStore_f,          &value, write_st);
    DRV_IOW_FIELD(lchip, CtcBsrCtlReset_t, CtcBsrCtlReset_resetCoreMetFifoProc0_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, CtcBsrCtlReset_t, CtcBsrCtlReset_resetCoreMetFifoShare_f,      &value, write_st);
    cmd = DRV_IOW(CtcBsrCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    /*CtcHsCtlReset CtcCsCtlReset*/
    for (i = 0; i < 4; i++)  /* there are 4 CtcHs/CtcCs in total TM2, 2 per DP */
    {
        /*HS*/
        cmd = DRV_IOR(CtcHsCtlReset_t, DRV_ENTRY_FLAG);
        index = DRV_INS(i, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
        value = 0;
        DRV_IOW_FIELD_NZ(lchip, CtcHsCtlReset_t, CtcHsCtlReset_resetCoreMcFec_f,     &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcHsCtlReset_t, CtcHsCtlReset_resetCoreMcMac_f,     &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcHsCtlReset_t, CtcHsCtlReset_resetCoreMcMacReg_f,  &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcHsCtlReset_t, CtcHsCtlReset_resetCoreMcPcs_f,     &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcHsCtlReset_t, CtcHsCtlReset_resetCoreMcPcsReg_f,  &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcHsCtlReset_t, CtcHsCtlReset_resetCoreMcuIntf_f,   &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcHsCtlReset_t, CtcHsCtlReset_resetCoreMcHataReg_f, &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcHsCtlReset_t, CtcHsCtlReset_resetCoreMcHata_f,    &value, write_st, i, 0);
        cmd = DRV_IOW(CtcHsCtlReset_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));

        /*CS*/
        cmd = DRV_IOR(CtcCsCtlReset_t, DRV_ENTRY_FLAG);
        index = DRV_INS(i, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
        value = 0;
        DRV_IOW_FIELD_NZ(lchip, CtcCsCtlReset_t, CtcCsCtlReset_resetCoreMcFec_f,     &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcCsCtlReset_t, CtcCsCtlReset_resetCoreMcMac_f,     &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcCsCtlReset_t, CtcCsCtlReset_resetCoreMcMacReg_f,  &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcCsCtlReset_t, CtcCsCtlReset_resetCoreMcPcs_f,     &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcCsCtlReset_t, CtcCsCtlReset_resetCoreMcPcsReg_f,  &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcCsCtlReset_t, CtcCsCtlReset_resetCoreMcHataReg_f, &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcCsCtlReset_t, CtcCsCtlReset_resetCoreMcHata_f,    &value, write_st, i, 0);
        cmd = DRV_IOW(CtcCsCtlReset_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
    }

    /*CtcFlexeCrossReset*/
    for (i = 0; i < 2; i++)
    {
        cmd = DRV_IOR(CtcFlexeCrossReset_t, DRV_ENTRY_FLAG);
        index = DRV_INS(i, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
        value = 0;
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeCrossReset_t, CtcFlexeCrossReset_resetFlexeCross_f,      &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeCrossReset_t, CtcFlexeCrossReset_resetFlexeCrossReg_f,   &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeCrossReset_t, CtcFlexeCrossReset_resetFlexeCrossRx_f,    &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeCrossReset_t, CtcFlexeCrossReset_resetFlexeCrossRxReg_f, &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeCrossReset_t, CtcFlexeCrossReset_resetFlexeCrossTx_f,    &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeCrossReset_t, CtcFlexeCrossReset_resetFlexeCrossTxReg_f, &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeCrossReset_t, CtcFlexeCrossReset_resetCoreMcuIntf_f,     &value, write_st, i, 0);
        cmd = DRV_IOW(CtcFlexeCrossReset_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
    }

    /*CtcFlexeShimReset*/
    for (i = 0; i < 2; i++)
    {
        cmd = DRV_IOR(CtcFlexeShimReset_t, DRV_ENTRY_FLAG);
        index = DRV_INS(i, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
        value = 0;
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeShimReset_t, CtcFlexeShimReset_resetFlexeMgr_f,     &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeShimReset_t, CtcFlexeShimReset_resetFlexeMgrReg_f,  &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeShimReset_t, CtcFlexeShimReset_resetFlexeShim_f,    &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeShimReset_t, CtcFlexeShimReset_resetFlexeShimReg_f, &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeShimReset_t, CtcFlexeShimReset_resetFlexeShimRx_f,  &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcFlexeShimReset_t, CtcFlexeShimReset_resetFlexeShimTx_f,  &value, write_st, i, 0);
        cmd = DRV_IOW(CtcFlexeShimReset_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
    }

    /*CtcAdEditCtlReset*/
    cmd = DRV_IOR(CtcAdEditCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, CtcAdEditCtlReset_t, CtcAdEditCtlReset_resetCoreDynamicAd_f,           &value, write_st);
    DRV_IOW_FIELD(lchip, CtcAdEditCtlReset_t, CtcAdEditCtlReset_resetCoreDynamicEdit_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CtcAdEditCtlReset_t, CtcAdEditCtlReset_resetCoreDynamicMiscKey_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, CtcAdEditCtlReset_t, CtcAdEditCtlReset_resetCoreEgrSclHash_f,          &value, write_st);
    DRV_IOW_FIELD(lchip, CtcAdEditCtlReset_t, CtcAdEditCtlReset_resetCoreFibHashHost1_f,        &value, write_st);
    DRV_IOW_FIELD(lchip, CtcAdEditCtlReset_t, CtcAdEditCtlReset_resetCoreGemPortHash_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CtcAdEditCtlReset_t, CtcAdEditCtlReset_resetCoreMplsHash_f,            &value, write_st);
    DRV_IOW_FIELD(lchip, CtcAdEditCtlReset_t, CtcAdEditCtlReset_resetCoreUserIdHashSclKeyCmp_f, &value, write_st);
    cmd = DRV_IOW(CtcAdEditCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    /*CtcIpeTxCtlReset*/
    cmd = DRV_IOR(CtcIpeTxCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, CtcIpeTxCtlReset_t, CtcIpeTxCtlReset_resetCoreCoppIpe_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeTxCtlReset_t, CtcIpeTxCtlReset_resetCoreEcmpDlb_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeTxCtlReset_t, CtcIpeTxCtlReset_resetCoreFlowAcc_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeTxCtlReset_t, CtcIpeTxCtlReset_resetCoreGlobalStats_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeTxCtlReset_t, CtcIpeTxCtlReset_resetCoreIpeFwd_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeTxCtlReset_t, CtcIpeTxCtlReset_resetCoreIpfixHash_f,   &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeTxCtlReset_t, CtcIpeTxCtlReset_resetCoreLinkAgg_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeTxCtlReset_t, CtcIpeTxCtlReset_resetCorePolicingIpe_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CtcIpeTxCtlReset_t, CtcIpeTxCtlReset_resetCoreStormCtl_f,    &value, write_st);
    cmd = DRV_IOW(CtcIpeTxCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    /*CtcEpeCtlReset*/
    cmd = DRV_IOR(CtcEpeCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCoreCoppEpe_f,       &value, write_st);
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCoreCoppGlbEpe_f,    &value, write_st);
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCoreEgressAclTcam_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCoreEpeAclOam_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCoreEpeHdrAdj_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCoreEpeHdrProc_f,    &value, write_st);
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCoreEpeNextHop_f,    &value, write_st);
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCoreLmStats_f,       &value, write_st);
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCoreParserEpe_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCorePolicingEpe_f,   &value, write_st);
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCoreEpePktRewrite_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CtcEpeCtlReset_t, CtcEpeCtlReset_resetCoreEpeHdrEdit_f,    &value, write_st);
    cmd = DRV_IOW(CtcEpeCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    /*CtcKeyCtlReset*/
    cmd = DRV_IOR(CtcKeyCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, CtcKeyCtlReset_t, CtcKeyCtlReset_resetCoreDsAging_f,       &value, write_st);
    DRV_IOW_FIELD(lchip, CtcKeyCtlReset_t, CtcKeyCtlReset_resetCoreDynamicFibKey_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CtcKeyCtlReset_t, CtcKeyCtlReset_resetCoreFibAcc_f,        &value, write_st);
    DRV_IOW_FIELD(lchip, CtcKeyCtlReset_t, CtcKeyCtlReset_resetCoreFibEngine_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcKeyCtlReset_t, CtcKeyCtlReset_resetCoreFibHashHost0_f,  &value, write_st);
    DRV_IOW_FIELD(lchip, CtcKeyCtlReset_t, CtcKeyCtlReset_resetCoreFlowHash_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, CtcKeyCtlReset_t, CtcKeyCtlReset_resetCoreLpmTcam_f,       &value, write_st);
    cmd = DRV_IOW(CtcKeyCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    /*CtcQMgrCtlReset*/
    cmd = DRV_IOR(CtcQMgrCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, CtcQMgrCtlReset_t, CtcQMgrCtlReset_resetCoreQMgrDeq_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcQMgrCtlReset_t, CtcQMgrCtlReset_resetCoreQMgrEnq_f,     &value, write_st);
    DRV_IOW_FIELD(lchip, CtcQMgrCtlReset_t, CtcQMgrCtlReset_resetCoreQMgrMsgStore_f,&value, write_st);
    cmd = DRV_IOW(CtcQMgrCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    /*CtcDpTxCtlReset*/
    for (i = 0; i < 2; i++)
    {
        cmd = DRV_IOR(CtcDpTxCtlReset_t, DRV_ENTRY_FLAG);
        index = DRV_INS(i, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
        value = 0;
        DRV_IOW_FIELD_NZ(lchip, CtcDpTxCtlReset_t, CtcDpTxCtlReset_resetCoreEpeSchedule_f, &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcDpTxCtlReset_t, CtcDpTxCtlReset_resetCoreMacSecEnc_f,   &value, write_st, i, 0);
        DRV_IOW_FIELD_NZ(lchip, CtcDpTxCtlReset_t, CtcDpTxCtlReset_resetCoreNetTx_f,       &value, write_st, i, 0);
        cmd = DRV_IOW(CtcDpTxCtlReset_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
    }

    /*CtcMiscCtlReset*/
    cmd = DRV_IOR(CtcMiscCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD_NZ(lchip, CtcMiscCtlReset_t, CtcMiscCtlReset_resetCoreCpuMac_f,     &value, write_st, 0, 0);
    DRV_IOW_FIELD_NZ(lchip, CtcMiscCtlReset_t, CtcMiscCtlReset_resetCoreHMacEngine_f, &value, write_st, 0, 0);
    DRV_IOW_FIELD_NZ(lchip, CtcMiscCtlReset_t, CtcMiscCtlReset_resetCoreMcuIntf_f,    &value, write_st, 0, 0);
    DRV_IOW_FIELD_NZ(lchip, CtcMiscCtlReset_t, CtcMiscCtlReset_resetCoreMdio0_f,      &value, write_st, 0, 0);
    DRV_IOW_FIELD_NZ(lchip, CtcMiscCtlReset_t, CtcMiscCtlReset_resetCoreMdio1_f,      &value, write_st, 0, 0);
    DRV_IOW_FIELD_NZ(lchip, CtcMiscCtlReset_t, CtcMiscCtlReset_resetCoreOamEngine_f,  &value, write_st, 0, 0);
    DRV_IOW_FIELD_NZ(lchip, CtcMiscCtlReset_t, CtcMiscCtlReset_resetCoreOobFc_f,      &value, write_st, 0, 0);
    DRV_IOW_FIELD_NZ(lchip, CtcMiscCtlReset_t, CtcMiscCtlReset_resetCoreSpnOam_f,     &value, write_st, 0, 0);
    DRV_IOW_FIELD_NZ(lchip, CtcMiscCtlReset_t, CtcMiscCtlReset_resetCoreTsEngine_f,   &value, write_st, 0, 0);
    cmd = DRV_IOW(CtcMiscCtlReset_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, write_st));

    cmd = DRV_IOR(NetRxWrEnCtl_t, DRV_ENTRY_FLAG);
    index = DRV_INS(0, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
    value_arr[0] = 0xffffffff;
    value_arr[1] = 0xff;
    DRV_IOW_FIELD_NZ(lchip, NetRxWrEnCtl_t, NetRxWrEnCtl_cfgWrEn0_f, value_arr, write_st, 0, 0);
    DRV_IOW_FIELD_NZ(lchip, NetRxWrEnCtl_t, NetRxWrEnCtl_cfgWrEn1_f, value_arr, write_st, 0, 0);
    DRV_IOW_FIELD_NZ(lchip, NetRxWrEnCtl_t, NetRxWrEnCtl_cfgWrEn2_f, value_arr, write_st, 0, 0);
    DRV_IOW_FIELD_NZ(lchip, NetRxWrEnCtl_t, NetRxWrEnCtl_cfgWrEn3_f, value_arr, write_st, 0, 0);
    cmd = DRV_IOW(NetRxWrEnCtl_t, DRV_ENTRY_FLAG);
    index = DRV_INS(0, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));

    cmd = DRV_IOR(CpuMacCtlResetCtl_t, DRV_ENTRY_FLAG);
    index = DRV_INS(0, 0);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
    value = 0;
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreCgPcs_f,        &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreLed_f,          &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreMii0_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreMii1_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreMii2_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreMii3_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCorePcs0_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCorePcs1_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCorePcs2_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCorePcs3_f,         &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreQuadSgmacReg_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreQuadSgmac_f,    &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreSharedFecReg_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreSharedMiiReg_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreSharedPcsReg_f, &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreXlgPcs0_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetCoreXlgPcs1_f,      &value, write_st);
    DRV_IOW_FIELD(lchip, CpuMacCtlResetCtl_t, CpuMacCtlResetCtl_resetSharedFec_f,        &value, write_st);
    cmd = DRV_IOW(CpuMacCtlResetCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));

    /* Gpo1: AN interrupt, serdes Gpo[02]; Gpo3: LT interrupt, serdes Gpo[09] */
    for(ctcxs_id = 0; ctcxs_id < 4; ctcxs_id++)
    {
        index = DRV_INS(ctcxs_id, 0);

        /*HssOctal0Cfg*/
        cmd = DRV_IOR(HssOctal0Cfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
        value = 2;
        DRV_IOW_FIELD(lchip, HssOctal0Cfg_t, HssOctal0Cfg_cfgHssOctal0GpoEnId1_f, &value, write_st);
        value = 9;
        DRV_IOW_FIELD(lchip, HssOctal0Cfg_t, HssOctal0Cfg_cfgHssOctal0GpoEnId3_f, &value, write_st);
        cmd = DRV_IOW(HssOctal0Cfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));

        /*HssOctal1Cfg*/
        cmd = DRV_IOR(HssOctal1Cfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
        value = 2;
        DRV_IOW_FIELD(lchip, HssOctal1Cfg_t, HssOctal1Cfg_cfgHssOctal1GpoEnId1_f, &value, write_st);
        value = 9;
        DRV_IOW_FIELD(lchip, HssOctal1Cfg_t, HssOctal1Cfg_cfgHssOctal1GpoEnId3_f, &value, write_st);
        cmd = DRV_IOW(HssOctal1Cfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));

        /*HssOctalCfg*/
        cmd = DRV_IOR(HssOctalCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
        value = 2;
        DRV_IOW_FIELD(lchip, HssOctalCfg_t, HssOctalCfg_cfgHssOctalGpoEnId1_f, &value, write_st);
        value = 9;
        DRV_IOW_FIELD(lchip, HssOctalCfg_t, HssOctalCfg_cfgHssOctalGpoEnId3_f, &value, write_st);
        cmd = DRV_IOW(HssOctalCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
    }

    index = DRV_INS(0, 0);
    cmd = DRV_IOR(CpuMacHssQuadCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
    value = 2;
    DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuadGpoEnId1_f, &value, write_st);
    value = 9;
    DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuadGpoEnId3_f, &value, write_st);
    cmd = DRV_IOW(CpuMacHssQuadCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, write_st));
    
    DP_DEBUG_FUNCTION_RETURN_PRINT();
        
    return CTC_E_NONE;
    
}
#endif

int32
_sys_tmm_datapath_check_subtype_pcsmode(uint8 lchip, uint8 pcs_mode, uint8 logic_serdes)
{
    if(DRV_CHIP_SUB_TYPE_1 == DRV_CHIP_SUB_TYPE(lchip))
    {
        if((CTC_CHIP_SERDES_LG_R1_MODE  == pcs_mode) || (CTC_CHIP_SERDES_CG_R2_MODE  == pcs_mode) || 
           (CTC_CHIP_SERDES_CCG_R4_MODE == pcs_mode) || (CTC_CHIP_SERDES_CDG_R8_MODE == pcs_mode) || 
           (CTC_CHIP_SERDES_PHY_MODE    == pcs_mode) || (CTC_CHIP_SERDES_RGMII_MODE  == pcs_mode))
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 15: serdes mode not support! logic_serdes %u, mode %u\n", 
                logic_serdes, pcs_mode);
            return CTC_E_NOT_SUPPORT;
        }
        if((32 > logic_serdes) || ((47 < logic_serdes) && (80 > logic_serdes)) || ((95 < logic_serdes) && (100 > logic_serdes)))
        {
            if((CTC_CHIP_SERDES_CG_MODE     == pcs_mode) || (CTC_CHIP_SERDES_XXVG_MODE   == pcs_mode) || 
               (CTC_CHIP_SERDES_LG_MODE     == pcs_mode) || (CTC_CHIP_SERDES_XLG_R2_MODE == pcs_mode))
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 16: serdes mode not support! logic_serdes %u, mode %u\n", 
                    logic_serdes, pcs_mode);
                return CTC_E_NOT_SUPPORT;
            }
        }
    }
    else if(DRV_CHIP_SUB_TYPE_2 == DRV_CHIP_SUB_TYPE(lchip))
    {
        if((CTC_CHIP_SERDES_LG_R1_MODE  == pcs_mode) || (CTC_CHIP_SERDES_CG_R2_MODE  == pcs_mode) || 
           (CTC_CHIP_SERDES_CCG_R4_MODE == pcs_mode) || (CTC_CHIP_SERDES_CDG_R8_MODE == pcs_mode) || 
           (CTC_CHIP_SERDES_PHY_MODE    == pcs_mode) || (CTC_CHIP_SERDES_RGMII_MODE  == pcs_mode))
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 17: serdes mode not support! logic_serdes %u, mode %u\n", 
                logic_serdes, pcs_mode);
            return CTC_E_NOT_SUPPORT;
        }
    }
    return CTC_E_NONE;
}

/* check datapath_cfg.txt param validity */
STATIC int32
_sys_tmm_datapath_cfg_param_check(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
    uint8 dual_cnt = 0;
    uint8 quad_cnt = 0;
    uint8 octl_cnt = 0;
    uint8 dual_flag = FALSE;
    uint8 quad_flag = FALSE;
    uint8 octl_flag = FALSE;
    uint8 lane_num  = 0;
    uint8 logic_serdes_id;
    uint8 physic_serdes;
    uint8 physic_serdes_used[CTC_DATAPATH_SERDES_NUM] = {0};
    ctc_datapath_serdes_prop_t *p_serdes = p_datapath_cfg->serdes;
    ctc_datapath_serdes_prop_t serdes_buf = {0};
    
    if(((DRV_CHIP_SUB_TYPE_1 == DRV_CHIP_SUB_TYPE(lchip)) || (DRV_CHIP_SUB_TYPE_2 == DRV_CHIP_SUB_TYPE(lchip))) && 
       ((0 != p_datapath_cfg->flexe_client_num[0]) || (0 != p_datapath_cfg->flexe_client_num[1])))
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 18: FlexE not support!\n");
        return CTC_E_NOT_SUPPORT;
    }

    /*100GR2 move lane 0 & 2 to lane 0 & 1*/
    for(logic_serdes_id = 0; logic_serdes_id < 32; logic_serdes_id += 2)
    {
        if(SYS_TMM_MODE_IS_PAM4(p_serdes[logic_serdes_id+1].mode))
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 10: serdes logic lane %u cannot be pam4 mode!\n", logic_serdes_id+1);
            return CTC_E_INVALID_CONFIG;
        }
        SYS_CONDITION_CONTINUE((0 == (logic_serdes_id % 4)) || 
            (CTC_CHIP_SERDES_CG_R2_MODE != p_serdes[logic_serdes_id].mode));
        sal_memcpy(&serdes_buf, &(p_serdes[logic_serdes_id]), sizeof(ctc_datapath_serdes_prop_t));
        sal_memcpy(&(p_serdes[logic_serdes_id]), &(p_serdes[logic_serdes_id-1]), sizeof(ctc_datapath_serdes_prop_t));
        sal_memcpy(&(p_serdes[logic_serdes_id-1]), &serdes_buf, sizeof(ctc_datapath_serdes_prop_t));

        p_serdes[logic_serdes_id].logical_serdes_id   = logic_serdes_id;
        p_serdes[logic_serdes_id-1].logical_serdes_id = logic_serdes_id-1;
    }
    for(logic_serdes_id = 48; logic_serdes_id < 80; logic_serdes_id += 2)
    {
        if(SYS_TMM_MODE_IS_PAM4(p_serdes[logic_serdes_id+1].mode))
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 10: serdes logic lane %u cannot be pam4 mode!\n", logic_serdes_id+1);
            return CTC_E_INVALID_CONFIG;
        }
        SYS_CONDITION_CONTINUE((0 == (logic_serdes_id % 4)) || 
            (CTC_CHIP_SERDES_CG_R2_MODE != p_serdes[logic_serdes_id].mode));
        sal_memcpy(&serdes_buf, &(p_serdes[logic_serdes_id]), sizeof(ctc_datapath_serdes_prop_t));
        sal_memcpy(&(p_serdes[logic_serdes_id]), &(p_serdes[logic_serdes_id-1]), sizeof(ctc_datapath_serdes_prop_t));
        sal_memcpy(&(p_serdes[logic_serdes_id-1]), &serdes_buf, sizeof(ctc_datapath_serdes_prop_t));

        p_serdes[logic_serdes_id].logical_serdes_id   = logic_serdes_id;
        p_serdes[logic_serdes_id-1].logical_serdes_id = logic_serdes_id-1;
    }

    for(logic_serdes_id = 0; logic_serdes_id < MCHIP_CAP(SYS_CAP_DMPS_SERDES_NUM_PER_SLICE); logic_serdes_id++)
    {
        CTC_ERROR_RETURN(_sys_tmm_datapath_check_subtype_pcsmode(lchip, p_serdes[logic_serdes_id].mode, logic_serdes_id));
        
        SYS_TMM_GET_LANE_NUM_BY_MODE(p_serdes[logic_serdes_id].mode, lane_num);

        if(SYS_TMM_IS_MODE_NONE(p_serdes[logic_serdes_id].mode))
        {
            p_serdes[logic_serdes_id].mode = CTC_CHIP_SERDES_NONE_MODE;
        }

        /*multi-lane mode check*/
        switch(lane_num)
        {
            case 2:
                if((0 != quad_cnt) || (0 != octl_cnt))
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 11: Serdes logic lane %u mode %u dual %u quad %u octl %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode, dual_cnt, quad_cnt, octl_cnt);
                    return CTC_E_INVALID_CONFIG;
                }
                /*invalid condition: current lane is 0 in a multi-lane series (!dual_flag), but no lane count before*/
                if((0 != dual_cnt) && (!dual_flag))
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 1: serdes logic lane %u mode %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode);
                    return CTC_E_INVALID_CONFIG;
                }
                /*invalid condition: current lane is 0 in a multi-lane series (0 == dual_cnt), but lane id is wrong*/
                if((0 == dual_cnt) && (0 != (logic_serdes_id % 2)))
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 2: Serdes logic lane %u mode %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode);
                    return CTC_E_INVALID_CONFIG;
                }
                
                dual_cnt++;
                dual_flag = TRUE;

                /*invalid condition: count of multi-lane exceeds max value*/
                if(2 < dual_cnt)
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 3: Serdes logic lane %u mode %u dual_cnt %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode, dual_cnt);
                    return CTC_E_INVALID_CONFIG;
                }
                /*if count of multi-lane reaches limit, set dual_flag to false for next multi-lane series*/
                else if(2 == dual_cnt)
                {
                    dual_flag = FALSE;
                    dual_cnt = 0;
                }
                break;
            case 4:
                if((0 != dual_cnt) || (0 != octl_cnt))
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 12: Serdes logic lane %u mode %u dual %u quad %u octl %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode, dual_cnt, quad_cnt, octl_cnt);
                    return CTC_E_INVALID_CONFIG;
                }
                /*invalid condition: current lane is 0 in a multi-lane series (!dual_flag), but no lane count before*/
                if((0 != quad_cnt) && (!quad_flag))
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 4: serdes logic lane %u mode %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode);
                    return CTC_E_INVALID_CONFIG;
                }
                /*invalid condition: current lane is 0 in a multi-lane series (0 == dual_cnt), but lane id is wrong*/
                if((0 == quad_cnt) && (0 != (logic_serdes_id % 4)))
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 5: Serdes logic lane %u mode %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode);
                    return CTC_E_INVALID_CONFIG;
                }
                
                quad_cnt++;
                quad_flag = TRUE;

                /*invalid condition: count of multi-lane exceeds max value*/
                if(4 < quad_cnt)
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 6: Serdes logic lane %u mode %u quad_cnt %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode, quad_cnt);
                    return CTC_E_INVALID_CONFIG;
                }
                /*if count of multi-lane reaches limit, set dual_flag to false for next multi-lane series*/
                else if(4 == quad_cnt)
                {
                    quad_flag = FALSE;
                    quad_cnt = 0;
                }
                break;
            case 8:
                if((0 != dual_cnt) || (0 != quad_cnt))
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 13: Serdes logic lane %u mode %u dual %u quad %u octl %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode, dual_cnt, quad_cnt, octl_cnt);
                    return CTC_E_INVALID_CONFIG;
                }
                /*invalid condition: current lane is 0 in a multi-lane series (!dual_flag), but no lane count before*/
                if((0 != octl_cnt) && (!octl_flag))
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 7: serdes logic lane %u mode %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode);
                    return CTC_E_INVALID_CONFIG;
                }
                /*invalid condition: current lane is 0 in a multi-lane series (0 == dual_cnt), but lane id is wrong*/
                if((0 == octl_cnt) && (0 != (logic_serdes_id % 8)))
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 8: Serdes logic lane %u mode %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode);
                    return CTC_E_INVALID_CONFIG;
                }
                
                octl_cnt++;
                octl_flag = TRUE;

                /*invalid condition: count of multi-lane exceeds max value*/
                if(8 < octl_cnt)
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 9: Serdes logic lane %u mode %u octl_cnt %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode, octl_cnt);
                    return CTC_E_INVALID_CONFIG;
                }
                /*if count of multi-lane reaches limit, set dual_flag to false for next multi-lane series*/
                else if(8 == octl_cnt)
                {
                    octl_flag = FALSE;
                    octl_cnt = 0;
                }
                break;
            case 1:
            default:
                if((0 != dual_cnt) || (0 != quad_cnt) || (0 != octl_cnt))
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 14: Serdes logic lane %u mode %u dual %u quad %u octl %u!\n", 
                        logic_serdes_id, p_serdes[logic_serdes_id].mode, dual_cnt, quad_cnt, octl_cnt);
                    return CTC_E_INVALID_CONFIG;
                }
                dual_cnt = 0;
                quad_cnt = 0;
                octl_cnt = 0;
                break;
        }

        /*QSGMII check*/
        if(((CTC_CHIP_SERDES_QSGMII_MODE == p_serdes[logic_serdes_id].mode) || 
            (TMM_SERDES_DYN_ALLOW_ALL == p_serdes[logic_serdes_id].is_dynamic)) && 
           (!SYS_TMM_IS_LOGICAL_SERDES_SUPPORT_QSGMII(logic_serdes_id)))
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Serdes logic lane %u cannot be QSGMII mode!\n", 
                p_serdes[logic_serdes_id].logical_serdes_id);
            return CTC_E_NOT_SUPPORT;
        }

        if(32 > logic_serdes_id % SYS_TMM_MAX_SERDES_NUM_PER_DP)
        {
            /*TXQM0&1 do not support 200G/400G*/
            if((CTC_CHIP_SERDES_CCG_R4_MODE == p_serdes[logic_serdes_id].mode) || 
               (CTC_CHIP_SERDES_CDG_R8_MODE == p_serdes[logic_serdes_id].mode))
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Serdes logic lane %u cannot be 200G/400G mode!\n", 
                    p_serdes[logic_serdes_id].logical_serdes_id);
                return CTC_E_NOT_SUPPORT;
            }

            /*50GR1 cannot appear in 1/3/5/7*/
            if((CTC_CHIP_SERDES_LG_R1_MODE == p_serdes[logic_serdes_id].mode) && (0 != logic_serdes_id % 2))
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Serdes logic lane %u cannot be 50GR1 mode!\n", 
                    p_serdes[logic_serdes_id].logical_serdes_id);
                return CTC_E_NOT_SUPPORT;
            }

            /*100GR2 cannot appear in 2/3/6/7*/
            if((CTC_CHIP_SERDES_CG_R2_MODE == p_serdes[logic_serdes_id].mode) && (1 < logic_serdes_id % 4))
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Serdes logic lane %u cannot be 100GR2 mode!\n", 
                    p_serdes[logic_serdes_id].logical_serdes_id);
                return CTC_E_NOT_SUPPORT;
            }

            if((DRV_CHIP_SUB_TYPE_4 == DRV_CHIP_SUB_TYPE(lchip)) && (logic_serdes_id < 96) &&
               (SYS_TMM_USELESS_ID8 != p_serdes[logic_serdes_id].physical_serdes_id) && 
               ((!SYS_TMM_IS_MODE_NONE(p_serdes[logic_serdes_id].mode)) || (TMM_SERDES_DYN_FORBID_ALL != p_serdes[logic_serdes_id].is_dynamic)))
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " CTC8186 do not support HS! logic id %u\n", logic_serdes_id);
                return CTC_E_NOT_SUPPORT;
            }
        }

        /*serdes map valid check*/
        physic_serdes = p_serdes[logic_serdes_id].physical_serdes_id;
        if(DRV_CHIP_SUB_TYPE_2 == DRV_CHIP_SUB_TYPE(lchip))
        {
            if((((11 < physic_serdes) && (16 > physic_serdes)) || ((27 < physic_serdes) && (32 > physic_serdes)) || 
                ((59 < physic_serdes) && (64 > physic_serdes)) ||((75 < physic_serdes) && (80 > physic_serdes))) && 
               (!SYS_TMM_IS_MODE_NONE(p_serdes[logic_serdes_id].mode)))
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Error 17: serdes id %u is forbidden!\n", physic_serdes);
                return CTC_E_NOT_SUPPORT;
            }
        }
        if(MCHIP_CAP(SYS_CAP_DMPS_SERDES_NUM_PER_SLICE) > physic_serdes)
        {
            if(SYS_TMM_MAP_SERDES_TO_HSS_IDX(logic_serdes_id) != SYS_TMM_MAP_SERDES_TO_HSS_IDX(physic_serdes))
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Serdes map out of bound! serdes id %u, logic id %u\n", 
                    physic_serdes, logic_serdes_id);
                return CTC_E_INVALID_CONFIG;
            }
            if(0 != physic_serdes_used[physic_serdes])
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " Serdes map duplicate! serdes id %u, logic id %u\n", 
                    physic_serdes, logic_serdes_id);
                return CTC_E_EXIST;
            }
            physic_serdes_used[physic_serdes] = 1;
        }
    }

    /*CPUMAC As Network check. when cpumac_dp0_network_en not equal cpumac_dp1_network_en, dno't support 40G/100G */
    if((p_usw_datapath_master[lchip]->cpumac_dp0_network_en != p_usw_datapath_master[lchip]->cpumac_dp1_network_en))
    {
        for(logic_serdes_id = 96; logic_serdes_id < 100; logic_serdes_id ++)
        {
            if((CTC_CHIP_SERDES_XLG_MODE == p_serdes[logic_serdes_id].mode) || (CTC_CHIP_SERDES_CG_MODE == p_serdes[logic_serdes_id].mode))
            {
                break;
            }
        }
        if(logic_serdes_id < 100)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " SerDes 96 - 99 cannot be 100GR4 or 40GCR4 mode!\n");
            return CTC_E_INVALID_CONFIG;
        }
    }
        
    return CTC_E_NONE;
}

#if (SDB_MEM_MODEL != SDB_MODE)
STATIC int32
_sys_tmm_datapath_core_clock_init(uint8 lchip, uint16 core_a)
{
#ifndef EMULATION_ENV
    PllCoreCfg_m core_cfg;
    PllLockMon_m core_mon;
    PllTsCfg_m   ts_cfg;
    PllTodCfg_m  tod_cfg;
    SupMiscCfg_m sm_cfg;
    uint32 cmd = 0;
    uint32 value = 0;
    uint32 islock = 0;

    if (1 == SDK_WORK_PLATFORM)
    {
        return DRV_E_NONE;
    }

    sal_memset(&core_cfg, 0, sizeof(PllCoreCfg_m));
    sal_memset(&core_mon, 0, sizeof(PllLockMon_m));

    /*reset core pll*/
    cmd = DRV_IOR(PllCoreCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_cfg));
    value = 1;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreReset_f, &value, &core_cfg);
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCorePllPwd_f, &value, &core_cfg);
    cmd = DRV_IOW(PllCoreCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_cfg));

    cmd = DRV_IOR(PllCoreCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_cfg));

    value = 20;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreMultInt_f, &value, &core_cfg);
    value = 0xc;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSic_f, &value, &core_cfg);
    value = 0x6;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSip_f, &value, &core_cfg);
    value = 1;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCorePostDiv_f, &value, &core_cfg);
    value = 0;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreDcoBypass_f, &value, &core_cfg);
    value = 1;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreIntFbk_f, &value, &core_cfg);
    value = 0;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCorePreDiv_f, &value, &core_cfg);
    value = 5;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSgain_f, &value, &core_cfg);
    value = 1;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSlock_f, &value, &core_cfg);

    cmd = DRV_IOW(PllCoreCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_cfg));

    sal_task_sleep(1);

    /*release reset core pll powerdown*/
    cmd = DRV_IOR(PllCoreCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_cfg));
    value = 0;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCorePllPwd_f, &value, &core_cfg);
    cmd = DRV_IOW(PllCoreCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_cfg));

    sal_task_sleep(1);

    /* release reset core pll reset */
    cmd = DRV_IOR(PllCoreCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_cfg));
    value = 0;
    DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreReset_f, &value, &core_cfg);
    cmd = DRV_IOW(PllCoreCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_cfg));

    sal_task_sleep(100);

    cmd = DRV_IOR(PllCoreCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_cfg));
    if(core_a == 800)
    {
        value = 31;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreMultInt_f, &value, &core_cfg);
        value = 0xc;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSic_f, &value, &core_cfg);
        value = 0x6;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSip_f, &value, &core_cfg);
        value = 3;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCorePostDiv_f, &value, &core_cfg);
        value = 0;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreDcoBypass_f, &value, &core_cfg);
        value = 1;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreIntFbk_f, &value, &core_cfg);
        value = 0;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCorePreDiv_f, &value, &core_cfg);
        value = 5;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSgain_f, &value, &core_cfg);
        value = 1;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSlock_f, &value, &core_cfg);
    }
    else if(core_a == 500)
    {
        value = 29;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreMultInt_f, &value, &core_cfg);
        value = 0xc;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSic_f, &value, &core_cfg);
        value = 0x6;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSip_f, &value, &core_cfg);
        value = 5;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCorePostDiv_f, &value, &core_cfg);
        value = 0;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreDcoBypass_f, &value, &core_cfg);
        value = 1;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreIntFbk_f, &value, &core_cfg);
        value = 0;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCorePreDiv_f, &value, &core_cfg);
        value = 5;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSgain_f, &value, &core_cfg);
        value = 1;
        DRV_IOW_FIELD(lchip, PllCoreCfg_t, PllCoreCfg_cfgPllCoreSlock_f, &value, &core_cfg);
    }
    else if(core_a != 1050)
    {
        return CTC_E_INVALID_PARAM;
    }
    cmd = DRV_IOW(PllCoreCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_cfg));

    sal_task_sleep(1);

    /*check pll lock*/
    cmd = DRV_IOR(PllLockMon_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_mon));
    if(0 == SDK_WORK_PLATFORM)
    {
        DRV_IOR_FIELD(lchip, PllLockMon_t, PllLockMon_monPllCoreLock_f, &islock, &core_mon);
        if(0 == islock)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [DATAPATH] pll cannot lock \n");
            return CTC_E_HW_NOT_LOCK;
        }
    }

    /*20201112 add*/
    /*SupMiscCfg.cfgPllCoreRefClkByp write 0*/
    cmd = DRV_IOR(SupMiscCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &sm_cfg));
    value = 0;
    DRV_IOW_FIELD(lchip, SupMiscCfg_t, SupMiscCfg_cfgPllCoreRefClkByp_f, &value, &sm_cfg);
    cmd = DRV_IOW(SupMiscCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &sm_cfg));

    /*Ts Clock Configuration*/
    cmd = DRV_IOR(PllTsCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ts_cfg));
    value = 0;
    DRV_IOW_FIELD(lchip, PllTsCfg_t, PllTsCfg_cfgPllTsPllPwd_f, &value, &ts_cfg);
    DRV_IOW_FIELD(lchip, PllTsCfg_t, PllTsCfg_cfgPllTsReset_f, &value, &ts_cfg);
    cmd = DRV_IOW(PllTsCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ts_cfg));

    /*TOD Clock Configuration*/
    cmd = DRV_IOR(PllTodCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &tod_cfg));
    value = 0;
    DRV_IOW_FIELD(lchip, PllTodCfg_t, PllTodCfg_cfgPllTodPllPwd_f, &value, &tod_cfg);
    DRV_IOW_FIELD(lchip, PllTodCfg_t, PllTodCfg_cfgPllTodReset_f, &value, &tod_cfg);
    cmd = DRV_IOW(PllTodCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &tod_cfg));
#endif

    return CTC_E_NONE;
}
#endif

#define _DYNAMIC__


int32
_sys_tmm_datapath_set_xpipe_mac_chan_remap(uint8 lchip, sys_datapath_lport_attr_t* port_attr)
{
    uint32  dp_mac_id;
    uint32  dp_chan_id;
    uint8   dp_id = SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id);
    uint16  lport = sys_usw_datapath_get_lport_with_mac(lchip, port_attr->mac_id);

    SYS_CONDITION_RETURN((SYS_COMMON_USELESS_MAC == lport), CTC_E_INVALID_CONFIG);

    /*1. DsNetRxPortToChanMap DsNetRxChanToPortMap*/
    if((SYS_TMM_USELESS_ID16 != port_attr->mac_id) && (SYS_TMM_USELESS_ID8 != port_attr->chan_id))
    {
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_netrx_port_chan_mapping2(lchip, port_attr->mac_id, 
        (port_attr->xpipe_en ==  CTC_PORT_XPIPE_TYPE_0 || port_attr->xpipe_en ==  CTC_PORT_XPIPE_TYPE_1 || port_attr->xpipe_en ==  CTC_PORT_XPIPE_TYPE_3) ?  port_attr->chan_id : port_attr->pmac_chanid));/*chan to port*/
    }
    if((SYS_TMM_USELESS_ID16 != port_attr->pmac_id) && (SYS_TMM_USELESS_ID8 != port_attr->pmac_chanid))
    {
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_netrx_port_chan_mapping1(lchip, port_attr->pmac_id, port_attr->chan_id)); /*port to chan*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_netrx_port_chan_mapping2(lchip, port_attr->pmac_id, 
        (port_attr->xpipe_en ==  CTC_PORT_XPIPE_TYPE_1 || port_attr->xpipe_en ==  CTC_PORT_XPIPE_TYPE_3) ? port_attr->pmac_chanid : port_attr->chan_id)); /*chan to port*/
    }

    /*2. IpeHeaderAdjustPhyPortMap*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_ipehdr_chanportmap(lchip, lport, port_attr->chan_id));

    /*3. EpeHeaderAdjustPhyPortMap*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_epehdr_chanportmap(lchip, lport, port_attr->chan_id));

    /*4. EpeSchedulePortToChanRa EpeScheduleChanToPortRa*/
    dp_mac_id  = SYS_TMM_GET_MACID_PER_DP(port_attr->pmac_id);
    dp_chan_id = SYS_TMM_GET_CHANN_PER_DP((port_attr->xpipe_en ==  CTC_PORT_XPIPE_TYPE_6) ? port_attr->chan_id : port_attr->pmac_chanid);
    CTC_ERROR_RETURN(_sys_tmm_datapath_epe_port_chan_map(lchip, dp_id, dp_mac_id, dp_chan_id));
    dp_mac_id  = SYS_TMM_GET_MACID_PER_DP(port_attr->mac_id);
    dp_chan_id = SYS_TMM_GET_CHANN_PER_DP((port_attr->xpipe_en ==  CTC_PORT_XPIPE_TYPE_6) ? port_attr->pmac_chanid : port_attr->chan_id);
    CTC_ERROR_RETURN(_sys_tmm_datapath_epe_port_chan_map(lchip, dp_id, dp_mac_id, dp_chan_id));

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_xpipe_resource_alloc(uint8 lchip, sys_datapath_lport_attr_t* port_attr)
{
    uint8 dp_id = SYS_TMM_GET_DP_ID_FROM_MACID(port_attr->mac_id);

    /*1. per-port config*/
    if((CTC_PORT_XPIPE_TYPE_0 != port_attr->xpipe_en) && (CTC_PORT_XPIPE_TYPE_6 != port_attr->xpipe_en))
    {
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_credit(lchip, port_attr, SYS_ALLOC_NORMAL, TRUE));
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_credit(lchip, port_attr, SYS_ALLOC_XPIPE_PMAC, TRUE));
        /*current chan_id is new allocated and exchanged before*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_bufretrv_credit(lchip, port_attr->chan_id, port_attr->speed_mode));
        
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_epe_credit(lchip, SYS_ALLOC_XPIPE_PMAC, port_attr));

        CTC_ERROR_RETURN(_sys_tmm_datapath_set_nettx_credit(lchip, SYS_ALLOC_XPIPE_PMAC, port_attr));
        CTC_ERROR_RETURN(_sys_tmm_datapath_nettx_timer_en(lchip, port_attr, SYS_ALLOC_NORMAL));
        CTC_ERROR_RETURN(_sys_tmm_datapath_nettx_timer_en(lchip, port_attr, SYS_ALLOC_XPIPE_PMAC));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_credit(lchip, port_attr, SYS_ALLOC_NORMAL, TRUE));
    }    

    /*2. multi-port config*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_set_dp_nettx_txthrd(lchip, dp_id));

    CTC_ERROR_RETURN(_sys_tmm_datapath_set_general_calendar(lchip, dp_id));

    CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_xg_lg_enable(lchip, dp_id));
    
    CTC_ERROR_RETURN(_sys_tmm_datapath_epe_xg_lg_enable(lchip, dp_id));   

    CTC_ERROR_RETURN(_sys_tmm_datapath_set_dp_netrx_wrr_weight(lchip, dp_id));

    CTC_ERROR_RETURN(_sys_tmm_datapath_set_dp_netrx_buf(lchip, dp_id));

    CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_wrr_weight(lchip));
    
    CTC_ERROR_RETURN(_sys_tmm_datapath_set_bufretrv_wrr_weight(lchip, dp_id));
    
    CTC_ERROR_RETURN(_sys_tmm_datapath_set_epe_wrr_weight(lchip, dp_id));

    CTC_ERROR_RETURN(_sys_tmm_datapath_set_xpipe_mac_chan_remap(lchip, port_attr));

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_show_xpipe(uint8 lchip)
{
    uint16 lport;
    uint8  gchip_id = 0;
    uint32 gport    = 0;
    uint16 cnt      = 0;
    uint16 i;
    sys_datapath_lport_attr_t* port_attr = NULL;
    sys_resource_manage_item_info_t *p_channel_arrange = p_usw_datapath_master[lchip]->resource_manage.channel_arrange;
    sys_resource_manage_item_info_t *p_macid_arrange   = p_usw_datapath_master[lchip]->resource_manage.macid_arrange;

    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip_id));

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------------------------\n");
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "MAC ID for P-MAC: \n");
    for(i = 0; i < 320; i++)
    {
        SYS_CONDITION_CONTINUE(!SYS_BMP_IS_SET(p_macid_arrange[i].arrange_type, 
            SYS_BMP_TO_VAL_U8(SYS_ARRANGE_XPIPE_PMAC_BMP)));
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%3u ", i);
        cnt++;
        if(0 == cnt % 16)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
        }
    }
    if(0 != cnt % 16)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    }
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------------------------\n");

    cnt = 0;
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "Channel ID for E-CHAN: \n");
    for(i = 0; i < 256; i++)
    {
        SYS_CONDITION_CONTINUE(!SYS_BMP_IS_SET(p_channel_arrange[i].arrange_type, 
            SYS_BMP_TO_VAL_U8(SYS_ARRANGE_XPIPE_PMAC_BMP)));
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%3u ", i);
        cnt++;
        if(0 == cnt % 16)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
        }
    }
    if(0 != cnt % 16)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "\n");
    }

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------------------------\n");
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " %-8s%-5s%-7s%-10s%-8s%-9s%-8s%-9s\n",
                      "GPort", "DP", "TXQM", "XPIPE-EN", "E-MAC", "E-CHAN", "P-MAC", "P-CHAN");
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------------------------\n");

    for(lport = 0; lport < SYS_USW_MAX_PORT_NUM_PER_CHIP; lport++)
    {
        SYS_CONDITION_CONTINUE(CTC_E_NONE != sys_tmm_datapath_get_port_attr(lchip, lport, &port_attr));
        SYS_CONDITION_CONTINUE((SYS_DMPS_NETWORK_PORT != port_attr->port_type) || (CTC_PORT_XPIPE_TYPE_0 == port_attr->xpipe_en));
        
        gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip_id, lport);
        
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " 0x%04x  %-5u%-7u%-10u%-8u%-9u%-8u%-9u\n",
                        gport, (port_attr->mac_id / 160), port_attr->txqm_id, port_attr->xpipe_en, 
                        port_attr->mac_id, port_attr->chan_id, port_attr->pmac_id, port_attr->pmac_chanid);
    }
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "-------------------------------------------------------------------\n");

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_ipehdr_chanportmap(uint8 lchip, uint16 lport, uint8 chan)
{
    uint32 cmd = 0;
    uint32 tmp_val32 = lport;
    IpeHeaderAdjustPhyPortMap_m  ipe_port_map;

    cmd = DRV_IOR(IpeHeaderAdjustPhyPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan, cmd, &ipe_port_map));

    DRV_IOW_FIELD(lchip, IpeHeaderAdjustPhyPortMap_t, IpeHeaderAdjustPhyPortMap_localPhyPort_f, &tmp_val32, &ipe_port_map);

    cmd = DRV_IOW(IpeHeaderAdjustPhyPortMap_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, chan, cmd, &ipe_port_map));

    return CTC_E_NONE;
}

int32
_sys_tmm_dynamic_switch_datapath(uint8 lchip, sys_tmm_ds_target_attr_t *p_ds_attr)
{
    uint8  lport_idx = 0;
    uint16 tmp_lport = 0;
    uint8  txqm_id   = 0;
    uint8  dp_num    = 1;
    uint8  dp_id_max = 2;
    uint8  dp_id     = SYS_TMM_GET_DP_ID_FROM_CHANID(p_ds_attr->lport_list[0].chan_id);
    sys_datapath_lport_attr_t* port_attr = NULL;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

    tmp_lport = p_ds_attr->lport_list[0].lport;
    CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, tmp_lport, &port_attr));
    if (SYS_DMPS_INACTIVE_NETWORK_PORT == port_attr->port_type)
    {
        return CTC_E_NONE;
    }

    for(lport_idx = 0; lport_idx < p_ds_attr->lport_num; lport_idx++)
    {
        if((dp_id != SYS_TMM_GET_DP_ID_FROM_CHANID(p_ds_attr->lport_list[lport_idx].chan_id)) && (1 == dp_num))
        {
            dp_num = 2;
        }

        SYS_CONDITION_CONTINUE(SYS_DS_LPORT_DROP == p_ds_attr->lport_list[lport_idx].upt_flag);

        tmp_lport = p_ds_attr->lport_list[lport_idx].lport;
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, tmp_lport, &port_attr));
        
        /* update NetTxPortStaticInfo_portMode_f here maybe */

#ifdef EMULATION_ENV
        CTC_ERROR_RETURN(_sys_tmm_datapath_qmgrshell_chan_wr_en(lchip, port_attr));
#endif
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_credit(lchip, port_attr, SYS_ALLOC_NORMAL, TRUE));

        if (SYS_DMPS_INACTIVE_NETWORK_PORT == port_attr->port_type)
        {
            CTC_ERROR_RETURN(_sys_tmm_datapath_set_bufretrv_credit(lchip, port_attr->chan_id, CTC_PORT_SPEED_MAX));
        }
        else
        {
            CTC_ERROR_RETURN(_sys_tmm_datapath_set_bufretrv_credit(lchip, port_attr->chan_id, port_attr->speed_mode));
        }
        
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_epe_credit(lchip, SYS_ALLOC_NORMAL, port_attr));

        CTC_ERROR_RETURN(_sys_tmm_datapath_set_nettx_credit(lchip, SYS_ALLOC_NORMAL, port_attr));

        if ((SYS_DMPS_NETWORK_PORT == port_attr->port_type) && 
                ((SYS_DS_LPORT_REMAIN == p_ds_attr->lport_list[lport_idx].upt_flag) || 
                        (SYS_DS_LPORT_ADD == p_ds_attr->lport_list[lport_idx].upt_flag)))
        {
            CTC_ERROR_RETURN(_sys_tmm_datapath_nettx_timer_en(lchip, port_attr, SYS_ALLOC_NORMAL));
        }

        CTC_ERROR_RETURN(_sys_tmm_datapath_set_epe_port_chan_mapping(lchip, SYS_ALLOC_NORMAL, port_attr));

        CTC_ERROR_RETURN(_sys_tmm_datapath_ipehdr_chanportmap(lchip, tmp_lport, port_attr->chan_id));

        if ((SYS_TMM_USELESS_ID16 != port_attr->mac_id) && (!SYS_TMM_IS_CPUMAC_PORT(port_attr->port_type)))
        {
            CTC_ERROR_RETURN(_sys_tmm_datapath_set_netrx_port_chan_mapping(lchip, port_attr->mac_id, port_attr->chan_id));
        }
    }

    dp_id_max = ((1 == dp_num) && (0 == dp_id)) ? 1 : 2;
    for(dp_id = ((2 == dp_num) ? 0 : dp_id); dp_id < dp_id_max; dp_id++)
    {
        /*check credit: qmgr, bufretrv, epe, nettx*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_check_credit_sum(lchip, dp_id));

        CTC_ERROR_RETURN(_sys_tmm_datapath_set_dp_nettx_txthrd(lchip, dp_id));
        
        SYS_TMM_GET_TXQM_BY_SERDES(p_ds_attr->serdes_list[0].logic_serdes_id, txqm_id);

        CTC_ERROR_RETURN(_sys_tmm_datapath_set_general_calendar(lchip, dp_id));

        tmp_lport = p_ds_attr->lport_list[0].lport;
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, tmp_lport, &port_attr));

        if (CTC_PORT_IF_FLEXE != port_attr->interface_type)
        {
            CTC_ERROR_RETURN(_sys_tmm_datapath_set_nettx_calendar(lchip, dp_id, SYS_TMM_GET_TXQM_PER_DP(txqm_id)));
            CTC_ERROR_RETURN(sys_tmm_set_mac_calendar(lchip, dp_id, SYS_TMM_GET_TXQM_PER_DP(txqm_id)));
        }
        else
        {
            CTC_ERROR_RETURN(_sys_tmm_datapath_set_nettx_calendar(lchip, dp_id, SYS_TMM_GET_TXQM_PER_DP(port_attr->txqm_id)));
        }

        CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_xg_lg_enable(lchip, dp_id));

        CTC_ERROR_RETURN(_sys_tmm_datapath_epe_xg_lg_enable(lchip, dp_id));

        CTC_ERROR_RETURN(_sys_tmm_datapath_set_dp_netrx_wrr_weight(lchip, dp_id));

        CTC_ERROR_RETURN(_sys_tmm_datapath_set_dp_netrx_buf(lchip, dp_id));
        
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_bufretrv_wrr_weight(lchip, dp_id));
        
        CTC_ERROR_RETURN(_sys_tmm_datapath_set_epe_wrr_weight(lchip, dp_id));
    }

    CTC_ERROR_RETURN(_sys_tmm_datapath_set_qmgr_wrr_weight(lchip));

    CTC_ERROR_RETURN(_sys_tmm_datapath_set_ipe_popslot(lchip, TRUE, NULL));

    return CTC_E_NONE;
}

#define __INIT__

int32
_sys_tmm_datapath_init_misc_info(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
    uint8 inner_lane_id = 0;
    uint8 serdes_mode = 0;
    uint8 lane_num = 0;
    uint8 dp_id;
    uint8 item;
    uint8 dp_chan_id;
    uint8 chan_id;
    uint16 lport;
    uint32 iloop1_chan = MCHIP_CAP(SYS_CAP_CHANID_ILOOP)+MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM);
    uint32 eloop1_chan = MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM);
    sys_cpumac_mapping_t* p_cpumac_map = p_usw_datapath_master[lchip]->cpumac_map;
    /*note: loop chan 114 & 116 (per dp) mapped to the same lport, but port_attr only save 1 chan_id, 
    so loop chan alloc datapath resource in seperated logic.*/
    uint32 misc_info[17][MISC_INFO_TYPE_BUTT] = 
    {
        /*cpumac*/
        {p_cpumac_map[0].lport,             p_cpumac_map[0].chan_id,          p_cpumac_map[0].mac_id, SYS_DMPS_CPU_MAC_PORT,    CTC_PORT_SPEED_MAX},
        {p_cpumac_map[1].lport,             p_cpumac_map[1].chan_id,          p_cpumac_map[1].mac_id, SYS_DMPS_CPU_MAC_PORT,    CTC_PORT_SPEED_MAX},
        {p_cpumac_map[2].lport,             p_cpumac_map[2].chan_id,          p_cpumac_map[2].mac_id, SYS_DMPS_CPU_MAC_PORT,    CTC_PORT_SPEED_MAX},
        {p_cpumac_map[3].lport,             p_cpumac_map[3].chan_id,          p_cpumac_map[3].mac_id, SYS_DMPS_CPU_MAC_PORT,    CTC_PORT_SPEED_MAX},
        /*sys_tmm_datapath_misc_port_t*/
        {SYS_DMPS_MISC_PORT_EUNIT0_ID,       MCHIP_CAP(SYS_CAP_CHANID_EUNIT0), SYS_TMM_USELESS_ID16,       SYS_DMPS_DMA_PORT,        CTC_PORT_SPEED_1G},
        {SYS_DMPS_MISC_PORT_EUNIT1_ID,       MCHIP_CAP(SYS_CAP_CHANID_EUNIT1), SYS_TMM_USELESS_ID16,       SYS_DMPS_DMA_PORT,        CTC_PORT_SPEED_1G},
        {SYS_DMPS_MISC_PORT_BYPASS_IPE_ID,   SYS_TMM_USELESS_ID8,              SYS_TMM_USELESS_ID16,       SYS_DMPS_MISC_OTHER_PORT, CTC_PORT_SPEED_MAX},
        {SYS_DMPS_MISC_PORT_DROP_ID,         MCHIP_CAP(SYS_CAP_CHANID_DROP),   SYS_TMM_USELESS_ID16,       SYS_DMPS_MISC_OTHER_PORT, CTC_PORT_SPEED_MAX},
        {SYS_DMPS_MISC_PORT_E2ILOOP_ID,      MCHIP_CAP(SYS_CAP_CHANID_ILOOP),  SYS_TMM_USELESS_ID16,       SYS_DMPS_ILOOP_PORT,      CTC_PORT_SPEED_200G},
        {SYS_DMPS_MISC_PORT_ELOOP_ID,        MCHIP_CAP(SYS_CAP_CHANID_ELOOP),  SYS_TMM_USELESS_ID16,       SYS_DMPS_ELOOP_PORT,      CTC_PORT_SPEED_200G},
        {SYS_DMPS_MISC_PORT_ILOOP1_ID,       iloop1_chan,                      SYS_TMM_USELESS_ID16,       SYS_DMPS_ILOOP_PORT,      CTC_PORT_SPEED_200G},
        {SYS_DMPS_MISC_PORT_ELOOP1_ID,       eloop1_chan,                      SYS_TMM_USELESS_ID16,       SYS_DMPS_ELOOP_PORT,      CTC_PORT_SPEED_200G},
        {SYS_DMPS_MISC_PORT_OAM_CPU_ID,      MCHIP_CAP(SYS_CAP_CHANID_OAM),    SYS_TMM_USELESS_ID16,       SYS_DMPS_OAM_PORT,        CTC_PORT_SPEED_50G},
        {SYS_DMPS_MISC_PORT_TO_CPU,          MCHIP_CAP(SYS_CAP_CHANID_DMA_RX0),SYS_TMM_USELESS_ID16,       SYS_DMPS_DMA_PORT,        CTC_PORT_SPEED_10G},
        {SYS_DMPS_MISC_PORT_HMAC,            MCHIP_CAP(SYS_CAP_CHANID_HMAC),   SYS_TMM_USELESS_ID16,       SYS_DMPS_MISC_OTHER_PORT, CTC_PORT_SPEED_MAX},
        {SYS_DMPS_MISC_PORT_SPINE_LEAF_PORT, SYS_TMM_USELESS_ID8,              SYS_TMM_USELESS_ID16,       SYS_DMPS_MISC_OTHER_PORT, CTC_PORT_SPEED_MAX},
        {SYS_DMPS_MISC_PORT_ILOOP_ID,        MCHIP_CAP(SYS_CAP_CHANID_ILOOP),  SYS_TMM_USELESS_ID16,       SYS_DMPS_ILOOP_PORT,      CTC_PORT_SPEED_MAX},
    };
    uint8  chan_start = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;
    sys_resource_manage_item_info_t *p_lport_arrange   = p_usw_datapath_master[lchip]->resource_manage.lport_arrange;
    sys_resource_manage_item_info_t *p_channel_arrange = p_usw_datapath_master[lchip]->resource_manage.channel_arrange;
    uint8  nw_lport_flag[SYS_TMM_MISC_PORT_START+1] = {0};
    uint16 lport_alloc[SYS_TMM_CPUMAC_SERDES_NUM] = {SYS_COMMON_USELESS_MAC, SYS_COMMON_USELESS_MAC, SYS_COMMON_USELESS_MAC, SYS_COMMON_USELESS_MAC};

    /*1. Reassign g_cpumac_mapping info*/
    /*1.1 reassign chan for dp0 CPUMAC NW*/
    if(p_usw_datapath_master[lchip]->cpumac_dp0_network_en)
    {
        misc_info[0][MISC_INFO_TYPE_PORT_TYPE] = SYS_DMPS_CPUMAC_NETWORK_PORT;
        misc_info[1][MISC_INFO_TYPE_PORT_TYPE] = SYS_DMPS_CPUMAC_NETWORK_PORT;
        p_cpumac_map[0].is_network = 1;
        p_cpumac_map[1].is_network = 1;
        chan_start = (uint8)(p_usw_datapath_master[lchip]->resource_manage.dp_lport_end[0] + 1);
        for(inner_lane_id = 0; inner_lane_id < SYS_TMM_CPUMAC_SERDES_NUM/2; inner_lane_id++)
        {
            SYS_CONDITION_CONTINUE(SYS_TMM_IS_MODE_NONE(p_datapath_cfg->serdes[SYS_TMM_CPUMAC_SERDES_START_ID + inner_lane_id].mode) && 
                                   (TMM_SERDES_DYN_FORBID_ALL == p_datapath_cfg->serdes[SYS_TMM_CPUMAC_SERDES_START_ID + inner_lane_id].is_dynamic));
            p_cpumac_map[inner_lane_id].chan_id = chan_start;
            chan_start++;
        }
    }
    /*1.2 reassign chan for dp1 CPUMAC NW*/
    if(p_usw_datapath_master[lchip]->cpumac_dp1_network_en)
    {
        misc_info[2][MISC_INFO_TYPE_PORT_TYPE] = SYS_DMPS_CPUMAC_NETWORK_PORT;
        misc_info[3][MISC_INFO_TYPE_PORT_TYPE] = SYS_DMPS_CPUMAC_NETWORK_PORT;
        p_cpumac_map[2].is_network = 1;
        p_cpumac_map[3].is_network = 1;
        chan_start = (uint8)(SYS_TMM_CHANNEL_NUM_PER_DP + p_usw_datapath_master[lchip]->resource_manage.dp_lport_end[1] - 
                             p_usw_datapath_master[lchip]->resource_manage.dp_lport_end[0]);
        for(inner_lane_id = SYS_TMM_CPUMAC_SERDES_NUM/2; inner_lane_id < SYS_TMM_CPUMAC_SERDES_NUM; inner_lane_id++)
        {
            SYS_CONDITION_CONTINUE(SYS_TMM_IS_MODE_NONE(p_datapath_cfg->serdes[SYS_TMM_CPUMAC_SERDES_START_ID + inner_lane_id].mode) && 
                                   (TMM_SERDES_DYN_FORBID_ALL == p_datapath_cfg->serdes[SYS_TMM_CPUMAC_SERDES_START_ID + inner_lane_id].is_dynamic));
            p_cpumac_map[inner_lane_id].chan_id = chan_start;
            chan_start++;
        }
    }
    /*1.3 reassign lport for CPUMAC, both NW or CPU, dual dp*/
    /*chan_2_logic_serdes to nw_lport_flag*/
    for(dp_id = 0; dp_id < SYS_TMM_DP_NUM; dp_id++)
    {   
        for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
        {
            SYS_CONDITION_CONTINUE(
                (p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag == SYS_CHAN_LPORT_OCCUPY_RSV) || 
                (p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].lport > SYS_TMM_MISC_PORT_START));
                
                nw_lport_flag[p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].lport] = 1;
        }
    }

    /*nw_lport_flag to lport_alloc, and misc_info by convenient*/
    inner_lane_id = 0;
    for(lport = 0; lport < (SYS_TMM_MISC_PORT_START+1); lport++)
    {
        SYS_CONDITION_CONTINUE(nw_lport_flag[lport]);
        for(; inner_lane_id < SYS_TMM_CPUMAC_SERDES_NUM; inner_lane_id++)
        {
            serdes_mode = p_datapath_cfg->serdes[SYS_TMM_CPUMAC_SERDES_START_ID + inner_lane_id].mode;
            SYS_TMM_GET_LANE_NUM_BY_MODE(serdes_mode, lane_num);
            SYS_CONDITION_BREAK(((!SYS_TMM_IS_MODE_NONE(serdes_mode)) && (0 == (inner_lane_id % lane_num))) || 
                (TMM_SERDES_DYN_FORBID_ALL != p_datapath_cfg->serdes[SYS_TMM_CPUMAC_SERDES_START_ID + inner_lane_id].is_dynamic));
            misc_info[inner_lane_id][MISC_INFO_TYPE_PORT_TYPE] = SYS_DMPS_RSV_PORT;
        }
        SYS_CONDITION_BREAK(inner_lane_id >= SYS_TMM_CPUMAC_SERDES_NUM);
        p_usw_datapath_master[lchip]->resource_manage.dp_lport_end[1]++;
        lport_alloc[inner_lane_id++] = lport;
    }
    /*lport_alloc to misc_info*/
    for(inner_lane_id = 0; inner_lane_id < SYS_TMM_CPUMAC_SERDES_NUM; inner_lane_id ++)
    {
        p_cpumac_map[inner_lane_id].lport = lport_alloc[inner_lane_id];
        misc_info[inner_lane_id][MISC_INFO_TYPE_CHAN_ID] = p_cpumac_map[inner_lane_id].chan_id;
        misc_info[inner_lane_id][MISC_INFO_TYPE_MAC_ID] = p_cpumac_map[inner_lane_id].mac_id;
        misc_info[inner_lane_id][MISC_INFO_TYPE_LPORT] = p_cpumac_map[inner_lane_id].lport;
    }


    /*2. Update misc ports soft tables: port_attr, chan_2_logic_serdes, p_lport_arrange, p_channel_arrange, usw_master info, etc*/
    for(item = 0; item < 17; item++)
    {
        lport = (uint16)misc_info[item][MISC_INFO_TYPE_LPORT];
        SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == lport);
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, lport, &port_attr));
        port_attr->chan_id    = misc_info[item][MISC_INFO_TYPE_CHAN_ID];
        port_attr->mac_id     = misc_info[item][MISC_INFO_TYPE_MAC_ID];
        port_attr->port_type  = misc_info[item][MISC_INFO_TYPE_PORT_TYPE];
        port_attr->slice_id   = 0;
        port_attr->serdes_num = 0;
        port_attr->speed_mode = misc_info[item][MISC_INFO_TYPE_SPEED];
        /*chan-lport map occupied for misc ports*/
        if(SYS_TMM_USELESS_ID8 != port_attr->chan_id)
        {
            dp_chan_id = SYS_TMM_GET_CHANN_PER_DP(port_attr->chan_id);
            dp_id = SYS_TMM_GET_DP_ID_FROM_CHANID(port_attr->chan_id);
            p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].lport = lport;
            if(4 > item) //0~3 cpumac serdes id mapping
            {
                p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].logic_serdes_id = p_cpumac_map[item].logic_serdes_id;
            }
            else
            {
                p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].logic_serdes_id = SYS_TMM_USELESS_ID8;
            }
            p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag = SYS_CHAN_LPORT_OCCUPY_IN_USE;
        }

        /*lport arrange occupied for misc ports*/
        if(SYS_TMM_LPORT_NUM > lport)
        {
            p_lport_arrange[lport].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_MISC_CHAN_BMP);
            p_lport_arrange[lport].using_stat   = SYS_RESOURCE_IN_USE;
        }
        /*mac id not recorded here*/
    }

    /*chan id arrange occupied for misc ports*/
    /*Even if 112~127 is not fully occupied, other free chan id cannot be used in NW ports, so keep placeholder of all misc chan*/
    for(dp_id = 0; dp_id < SYS_TMM_DP_NUM; dp_id++)
    {
        for(dp_chan_id = 112; dp_chan_id < 128; dp_chan_id++)
        {
            if((112 == dp_chan_id) || (113 == dp_chan_id))
            {
                if(((0 == dp_id) && (p_usw_datapath_master[lchip]->cpumac_dp0_network_en)) || 
                    ((1 == dp_id) && (p_usw_datapath_master[lchip]->cpumac_dp1_network_en)))
                {
                    /*for cpumac NW, channel arrange will */
                    continue;
                }
            }
            
            chan_id = SYS_GET_CHANNEL_BY_DP_CHANID(dp_chan_id, dp_id);
            p_channel_arrange[chan_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_MISC_CHAN_BMP);
            p_channel_arrange[chan_id].using_stat   = SYS_RESOURCE_IN_USE;

            if(SYS_CHAN_LPORT_OCCUPY_RSV == p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag)
            {
                p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].lport = SYS_TMM_USELESS_ID16;
                p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].logic_serdes_id = SYS_TMM_USELESS_ID8;
                p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag = SYS_CHAN_LPORT_OCCUPY_IN_USE;
            }
        }
    }

    /*these soft tables are just for display*/
    p_usw_datapath_master[lchip]->oam_chan   = MCHIP_CAP(SYS_CAP_CHANID_OAM);
    p_usw_datapath_master[lchip]->dma_chan   = MCHIP_CAP(SYS_CAP_CHANID_DMA_RX0);
    p_usw_datapath_master[lchip]->iloop_chan = MCHIP_CAP(SYS_CAP_CHANID_ILOOP);
    p_usw_datapath_master[lchip]->eloop_chan = MCHIP_CAP(SYS_CAP_CHANID_ELOOP);

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_init_resource_arrange(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
    uint16 lport;
    uint16 mac_id;
    uint16 chan_id;
    uint16 count = 0;
    uint16 dp_mac_id;
    uint16 dp_chan_id;
    uint16 lport_ext = 0;
    uint8  dp_id;
    uint8  max_num;
    uint8  txqm_id;
    uint8  xpipe_num0      = p_datapath_cfg->xpipe_num[0];
    uint8  xpipe_num1      = p_datapath_cfg->xpipe_num[1];
    uint8  flexe_chan_num0 = p_datapath_cfg->flexe_client_num[0];
    uint8  flexe_chan_num1 = p_datapath_cfg->flexe_client_num[1];
    sys_datapath_lport_attr_t*  port_attr = NULL;
    sys_resource_manage_item_info_t *p_lport_arrange   = p_usw_datapath_master[lchip]->resource_manage.lport_arrange;
    sys_resource_manage_item_info_t *p_channel_arrange = p_usw_datapath_master[lchip]->resource_manage.channel_arrange;
    sys_resource_manage_item_info_t *p_macid_arrange   = p_usw_datapath_master[lchip]->resource_manage.macid_arrange;

    p_usw_datapath_master[lchip]->resource_manage.flexe_client_num[0] = flexe_chan_num0;
    p_usw_datapath_master[lchip]->resource_manage.flexe_client_num[1] = flexe_chan_num1;
    p_usw_datapath_master[lchip]->resource_manage.xpipe_num[0]        = xpipe_num0;
    p_usw_datapath_master[lchip]->resource_manage.xpipe_num[1]        = xpipe_num1;
    MCHIP_CAP(SYS_CAP_XPIPE_PORT_NUM) = xpipe_num0 + xpipe_num1;

    /*1. lport & channel arrange*/
    /*arrange network lport & channel*/
    for(dp_id = 0; dp_id < SYS_TMM_DP_NUM; dp_id++)
    {
        for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
        {
            SYS_CONDITION_CONTINUE(SYS_TMM_IS_MISC_CHAN(dp_id, dp_chan_id));
            SYS_CONDITION_CONTINUE(SYS_CHAN_LPORT_OCCUPY_RSV == 
                p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag);
            
            chan_id = SYS_GET_CHANNEL_BY_DP_CHANID(dp_chan_id, dp_id);
            lport   = p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].lport;

            p_channel_arrange[chan_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_NETWORK_PORT_BMP);
            p_channel_arrange[chan_id].using_stat = 
                (SYS_CHAN_LPORT_OCCUPY_IN_USE == p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag) ? 
                SYS_RESOURCE_IN_USE : SYS_RESOURCE_FREE;

            p_lport_arrange[lport].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_NETWORK_PORT_BMP);
            p_lport_arrange[lport].using_stat = 
                (SYS_CHAN_LPORT_OCCUPY_IN_USE == p_usw_datapath_master[lchip]->chan_2_logic_serdes[dp_id][dp_chan_id].occupy_flag) ? 
                SYS_RESOURCE_IN_USE : SYS_RESOURCE_FREE;
        }
    }

    /*arrange flexe lport*/
    /*max_num = flexe_chan_num0 + flexe_chan_num1;
    for(lport = 0; lport < SYS_RSV_PORT_START; lport++)
    {
        SYS_CONDITION_CONTINUE(0 != p_lport_arrange[lport].arrange_type);
        
        p_lport_arrange[lport].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_FLEXE_PORT_BMP);
        p_lport_arrange[lport].using_stat   = SYS_RESOURCE_FREE;
        count++;
        SYS_CONDITION_BREAK(count >= max_num);
    }
    if(count < max_num)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " flexe lport out of max value! \n");
        return CTC_E_NOT_SUPPORT;
    }*/

    /*lport for ext port*/
    for(lport = 0; lport < SYS_TMM_LPORT_NUM; lport++)
    {
        SYS_CONDITION_CONTINUE(0 != p_lport_arrange[lport].arrange_type);
        
        p_lport_arrange[lport].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_EXT_PORT_BMP);
        p_lport_arrange[lport].using_stat   = SYS_RESOURCE_FREE;
    }

    for(dp_id = 0; dp_id < SYS_TMM_DP_NUM; dp_id++)
    {
        /*1.4 arrange flexe channel*/
        count = 0;
        max_num = (0 == dp_id) ? flexe_chan_num0 : flexe_chan_num1;
        for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
        {
            SYS_CONDITION_BREAK(count >= max_num);
            chan_id = SYS_GET_CHANNEL_BY_DP_CHANID(dp_chan_id, dp_id);
            SYS_CONDITION_CONTINUE(0 != p_channel_arrange[chan_id].arrange_type);
            
            p_channel_arrange[chan_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_FLEXE_PORT_BMP);
            p_channel_arrange[chan_id].using_stat   = SYS_RESOURCE_FREE;
            count++;
        }
        if(count < max_num)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% FlexE channel out of max value! \n");
            return CTC_E_NOT_SUPPORT;
        }
        
        /*1.5 arrange xpipe pmac channel*/
        count = 0;
        max_num = (0 == dp_id) ? xpipe_num0 : xpipe_num1;
        for(dp_chan_id = 0; dp_chan_id < SYS_TMM_CHANNEL_NUM_PER_DP; dp_chan_id++)
        {
            SYS_CONDITION_BREAK(count >= max_num);
            chan_id = SYS_GET_CHANNEL_BY_DP_CHANID(dp_chan_id, dp_id);
            SYS_CONDITION_CONTINUE(0 != p_channel_arrange[chan_id].arrange_type);
            
            p_channel_arrange[chan_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_XPIPE_PMAC_BMP);
            p_channel_arrange[chan_id].using_stat   = SYS_RESOURCE_FREE;
            count++;
        }
        if(count < max_num)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% X-PIPE channel out of max value! \n");
            return CTC_E_NOT_SUPPORT;
        }
    }

    /*macid arrange*/
    for(mac_id = 0; mac_id < SYS_TMM_MAX_MAC_NUM; mac_id++)
    {
        txqm_id = SYS_TMM_GET_TXQM_BY_MACID(mac_id);
        if(SYS_TMM_IS_PCS_X16(txqm_id))
        {
            if(32 > SYS_TMM_GET_MACID_PER_TXQM(mac_id) && (0 != mac_id % 4))
            {
                p_macid_arrange[mac_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_NETWORK_PORT_BMP) | 
                                                       SYS_BMP_TO_VAL_U8(SYS_ARRANGE_XPIPE_PMAC_BMP);
                lport = sys_usw_datapath_get_lport_with_mac(lchip, mac_id);
                if(SYS_COMMON_USELESS_MAC == lport)
                {
                    p_macid_arrange[mac_id].using_stat = SYS_RESOURCE_FREE;
                }
                else
                {
                    p_macid_arrange[mac_id].using_stat = SYS_RESOURCE_IN_USE;
                }
            }
            lport = sys_usw_datapath_get_lport_with_mac(lchip, mac_id);
            SYS_CONDITION_CONTINUE(SYS_COMMON_USELESS_MAC == lport);
            CTC_ERROR_RETURN(sys_tmm_datapath_get_port_attr(lchip, lport, &port_attr));
            if(SYS_DMPS_NETWORK_PORT == port_attr->port_type)
            {
                p_macid_arrange[mac_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_NETWORK_PORT_BMP);
                p_macid_arrange[mac_id].using_stat   = SYS_RESOURCE_IN_USE;
            }
            else
            {
                p_macid_arrange[mac_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_NETWORK_PORT_BMP) | 
                                                       SYS_BMP_TO_VAL_U8(SYS_ARRANGE_XPIPE_PMAC_BMP);
                p_macid_arrange[mac_id].using_stat   = SYS_RESOURCE_FREE;
            }
        }
        else
        {
            dp_mac_id = SYS_TMM_GET_MACID_PER_DP(mac_id);
            if(120 <= dp_mac_id)
            {
                if(127 >= dp_mac_id)
                {
                    p_macid_arrange[mac_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_NETWORK_PORT_BMP) |
                                                           SYS_BMP_TO_VAL_U8(SYS_ARRANGE_FLEXE_PORT_BMP);
                    p_macid_arrange[mac_id].using_stat   = SYS_RESOURCE_IN_USE;
                }
                else if(135 >= dp_mac_id)
                {
                    p_macid_arrange[mac_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_XPIPE_PMAC_BMP) | 
                                                           SYS_BMP_TO_VAL_U8(SYS_ARRANGE_FLEXE_PORT_BMP);
                    p_macid_arrange[mac_id].using_stat   = SYS_RESOURCE_FREE;
                }
                else
                {
                    p_macid_arrange[mac_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_FLEXE_PORT_BMP);
                    p_macid_arrange[mac_id].using_stat   = SYS_RESOURCE_FREE;
                }
            }
            else if(80 <= dp_mac_id)
            {
                if(87 >= dp_mac_id)
                {
                    p_macid_arrange[mac_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_NETWORK_PORT_BMP) |
                                                           SYS_BMP_TO_VAL_U8(SYS_ARRANGE_FLEXE_PORT_BMP);
                    p_macid_arrange[mac_id].using_stat   = SYS_RESOURCE_IN_USE;
                }
                else if(95 >= dp_mac_id)
                {
                    p_macid_arrange[mac_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_XPIPE_PMAC_BMP) | 
                                                           SYS_BMP_TO_VAL_U8(SYS_ARRANGE_FLEXE_PORT_BMP);
                    p_macid_arrange[mac_id].using_stat   = SYS_RESOURCE_FREE;
                }
                else
                {
                    p_macid_arrange[mac_id].arrange_type = SYS_BMP_TO_VAL_U8(SYS_ARRANGE_FLEXE_PORT_BMP);
                    p_macid_arrange[mac_id].using_stat   = SYS_RESOURCE_FREE;
                }
            }
        }
    }

    /*update ext port start id*/
    sys_tmm_datapath_get_extport_start_id(lchip, &lport_ext);
    SYS_INTERNAL_PORT_START = lport_ext;

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_init_build_cpumac_serdes_info(uint8 lchip, ctc_datapath_serdes_prop_t* p_serdes_raw)
{
    uint8  hss_id           = SYS_TMM_CPUMAC_HSS_ID;
    uint8  inner_lane_id    = 0;
    uint8  width            = 0;
    uint8  div              = 0;
    uint8  lane_num         = 0;
    uint8  need_add         = FALSE;
    int32  ret              = CTC_E_NONE;
    
    sys_datapath_hss_attribute_t* p_hss_vec    = NULL;
    sys_datapath_serdes_info_t*   p_serdes     = NULL;

    p_hss_vec = ctc_vector_get(p_usw_datapath_master[lchip]->p_hss_vector, hss_id);
    if (p_hss_vec == NULL)
    {
        p_hss_vec = (sys_datapath_hss_attribute_t*)mem_malloc(MEM_SYSTEM_MODULE, sizeof(sys_datapath_hss_attribute_t));
        if(NULL == p_hss_vec)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% No memory \n");
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_hss_vec, 0, sizeof(sys_datapath_hss_attribute_t));
        for(inner_lane_id = 0; inner_lane_id < HSS15G_LANE_NUM; inner_lane_id++)
        {
            p_hss_vec->serdes_info[inner_lane_id].physical_serdes_id = SYS_TMM_USELESS_ID8;
        }
        need_add = TRUE;
    }

    /*1. fill serdes info soft table*/
    p_hss_vec->hss_id = hss_id;
    inner_lane_id = SYS_TMM_MAP_SERDES_TO_LANE_ID(p_serdes_raw->logical_serdes_id);
    p_serdes = &(p_hss_vec->serdes_info[inner_lane_id]);
    SYS_TMM_GET_LANE_NUM_BY_MODE(p_serdes_raw->mode, lane_num);
    
    p_serdes->lane_id            = inner_lane_id;
    p_serdes->group              = inner_lane_id;
    p_serdes->pcs_l_id           = inner_lane_id % lane_num;        //0~lane_num-1
    p_serdes->physical_serdes_id = p_serdes_raw->physical_serdes_id;
    p_serdes->mode               = p_serdes_raw->mode;
    p_serdes->pll_sel            = 1;
    p_serdes->bit_width          = width;
    p_serdes->rate_div           = div;
    p_serdes->overclocking_speed = 0;
    p_serdes->rx_polarity        = p_serdes_raw->rx_polarity;       //polarity
    p_serdes->tx_polarity        = p_serdes_raw->tx_polarity;       //polarity
    p_serdes->is_dyn             = p_serdes_raw->is_dynamic;

    /*mapping CTC_CHIP_SERDES_XLG_R2_MODE to CTC_CHIP_SERDES_LG_MODE & CTC_CHIP_SERDES_OCS_MODE_20_625G*/
    if(CTC_CHIP_SERDES_XLG_R2_MODE == p_serdes_raw->mode)
    {
        p_serdes->mode = CTC_CHIP_SERDES_LG_MODE;
        p_serdes->overclocking_speed = CTC_CHIP_SERDES_OCS_MODE_20_625G;
    }

    if(need_add)
    {
        ctc_vector_add(p_usw_datapath_master[lchip]->p_hss_vector, hss_id, (void*)p_hss_vec);
    }

    return ret;
}

int32
sys_tmm_datapath_init_build_cpumac_lport_info(uint8 lchip)
{
    uint8  inner_lane_id    = 0;
    uint8  cpumac_idx       = 0;
    
    sys_datapath_hss_attribute_t* p_hss_vec = NULL;
    sys_datapath_serdes_info_t*   p_serdes  = NULL;
    sys_cpumac_mapping_t* p_cpumac_map = p_usw_datapath_master[lchip]->cpumac_map;

    /*2. build serdes-lport info & port_attr*/
    p_hss_vec = ctc_vector_get(p_usw_datapath_master[lchip]->p_hss_vector, SYS_TMM_CPUMAC_HSS_ID);
    SYS_CONDITION_RETURN(NULL == p_hss_vec, CTC_E_NONE);
    
    for(inner_lane_id = 0; inner_lane_id < SYS_TMM_CPUMAC_SERDES_NUM; inner_lane_id++)
    {
        p_serdes = &(p_hss_vec->serdes_info[inner_lane_id]);
        if(SYS_TMM_IS_MODE_NONE(p_serdes->mode))
        {
            p_serdes->lport   = SYS_TMM_USELESS_ID16;
            p_serdes->chan_id = SYS_TMM_USELESS_ID16;
            p_serdes->port_num = 0;
        }
        else if(p_serdes->lane_id >= p_serdes->pcs_l_id)
        {
            cpumac_idx = p_serdes->lane_id - p_serdes->pcs_l_id;
            if(4 > cpumac_idx)
            {
                p_serdes->lport   = p_cpumac_map[cpumac_idx].lport;
                p_serdes->chan_id = p_cpumac_map[cpumac_idx].chan_id;
                p_serdes->port_num = 1;
            }
        }
        CTC_ERROR_RETURN(sys_tmm_datapath_build_cpumac_port_attr(lchip, p_serdes));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_datapath_init_db(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
    uint8  logic_serdes_id = 0;
    uint16 lport     = 0;
    sys_cpumac_mapping_t cpumac_map[SYS_TMM_CPUMAC_SERDES_NUM] = 
    {
       /*serdes_id, mac_id, chan_id, lport, is_network*/
        {96,        320,    112,     240,     0}, 
        {97,        321,    113,     241,     0}, 
        {98,        322,    240,     242,     0}, 
        {99,        323,    241,     243,     0}
    };

    /*clear all port_attr */
    for(lport = 0; lport < MCHIP_CAP(SYS_CAP_PER_SLICE_PORT_NUM); lport++)
    {
        CTC_ERROR_RETURN(_sys_tmm_datapath_clear_port_attr(lchip, lport));
    }

    sal_memset(p_usw_datapath_master[lchip]->chan_2_logic_serdes, 0, 
        SYS_TMM_DP_NUM * SYS_TMM_CHANNEL_NUM_PER_DP * sizeof(sys_channel_2_logic_serdes_map_t));

    p_usw_datapath_master[lchip]->core_plla = p_datapath_cfg->core_frequency_a;
    p_usw_datapath_master[lchip]->cpumac_dp0_network_en = p_datapath_cfg->cpumac_dp0_network_en;
    p_usw_datapath_master[lchip]->cpumac_dp1_network_en = p_datapath_cfg->cpumac_dp1_network_en;
    p_usw_datapath_master[lchip]->bpe_full_mode = p_datapath_cfg->bpe_full_mode;

    p_usw_datapath_master[lchip]->wlan_enable = p_datapath_cfg->wlan_enable;
    p_usw_datapath_master[lchip]->dot1ae_enable = p_datapath_cfg->dot1ae_enable;

    sal_memset(&(p_usw_datapath_master[lchip]->resource_manage), 0, sizeof(sys_resource_manage_t));
    sal_memset(p_usw_datapath_master[lchip]->ext_lport_map, 0xff, 512 * sizeof(uint16));
    sal_memcpy(p_usw_datapath_master[lchip]->cpumac_map, cpumac_map, SYS_TMM_CPUMAC_SERDES_NUM * sizeof(sys_cpumac_mapping_t));

    /*normal network port*/
    for (logic_serdes_id = 0; logic_serdes_id < SYS_TMM_MAX_SERDES_NUM; logic_serdes_id++)
    {
        CTC_ERROR_RETURN(sys_tmm_datapath_init_build_serdes_info(lchip, &(p_datapath_cfg->serdes[logic_serdes_id])));
    }
    CTC_ERROR_RETURN(sys_tmm_datapath_init_build_lport_info(lchip, p_datapath_cfg));


    CTC_ERROR_RETURN(_sys_tmm_datapath_init_misc_info(lchip, p_datapath_cfg));


    /*cpumac*/
    for (logic_serdes_id = SYS_TMM_CPUMAC_SERDES_START_ID; 
         logic_serdes_id < SYS_TMM_CPUMAC_SERDES_START_ID + SYS_TMM_CPUMAC_SERDES_NUM; logic_serdes_id++)
    {
        if (SYS_TMM_IS_SERDES_ABANDON(p_datapath_cfg->serdes[logic_serdes_id].mode, 
                                      p_datapath_cfg->serdes[logic_serdes_id].is_dynamic))  /* for powerdown use */
        {
            continue;
        }
        CTC_ERROR_RETURN(sys_tmm_datapath_init_build_cpumac_serdes_info(lchip, &(p_datapath_cfg->serdes[logic_serdes_id])));
    }

    CTC_ERROR_RETURN(sys_tmm_datapath_init_build_cpumac_lport_info(lchip));

    CTC_ERROR_RETURN(sys_tmm_datapath_init_resource_arrange(lchip, p_datapath_cfg));

    return CTC_E_NONE;
}

#if (SDB_MEM_MODEL != SDB_MODE)
STATIC int32
_sys_tmm_datapath_omitted_table_init(uint8 lchip)
{
    uint32 cmd = 0;
#ifdef PCS_IMG
    uint32 data[8] = {0};  // 256 bit
    uint32 entry_id = 0;
#endif
    uint32 val32  = 0;
    uint32 tbl_id = 0;
    uint32 fld_id = 0;
    //uint32 cmd    = 0;
    uint32 index  = 0;
    uint32 step   = 0;
    uint32 factor = 0;
    uint8  txqm_id = 0;
    uint8  entry = 0;
    uint8  hscs[] = {0, 0, 1, 1, 0, 0, 1, 1};
    uint8  idx[] = {0, 1, 0, 1, 2, 3, 2, 3};
    McMacPcsCfg_m     pcs_cfg;
    McMacRxChanMap_m  rx_chanmap;

    DP_DEBUG_FUNCTION_CALLED_PRINT();

#ifdef PCS_IMG
    entry_id = DRV_INS(0, 0);

    // clear QMgrShellChanWrEnCtl
    cmd = DRV_IOW(QMgrShellChanWrEnCtl_t, QMgrShellChanWrEnCtl_chanWrEn_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, entry_id, cmd, data));
#endif

    sal_memset(&pcs_cfg, 0, sizeof(McMacPcsCfg_m));
    sal_memset(&rx_chanmap, 0, sizeof(McMacRxChanMap_m));

    /* #2, read HW table:  */
    tbl_id = McMacPcsCfg_t;
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);

    for (txqm_id = 0; txqm_id < SYS_TMM_TXQM_NUM_PER_DP*SYS_TMM_DP_NUM; txqm_id++)
    {
        SYS_CONDITION_CONTINUE(p_usw_datapath_master[lchip]->hscs_down_flag[hscs[txqm_id]][idx[txqm_id]]);

        index = DRV_INS(txqm_id, 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_cfg));

        /* ##2.1. calc step */
        val32 = 0;
        step = McMacPcsCfg_mcMacPcsCfg_1_cfgMcMacPcsSyncStatusDisable_f - McMacPcsCfg_mcMacPcsCfg_0_cfgMcMacPcsSyncStatusDisable_f;
        for (factor = 0; factor < SYS_TMM_MAX_MAC_NUM_PER_TXQM; factor++)
        {
            /* ##2.2. modify field value */
            /* ###2.2.1. */
            fld_id = McMacPcsCfg_mcMacPcsCfg_0_cfgMcMacPcsSyncStatusDisable_f + step*factor;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &pcs_cfg, txqm_id, 0);
        }
        /* #3, write HW table: */
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_cfg));
    }

    for (txqm_id = 0; txqm_id < SYS_TMM_TXQM_NUM_PER_DP*SYS_TMM_DP_NUM; txqm_id++)
    {
        SYS_CONDITION_CONTINUE(p_usw_datapath_master[lchip]->hscs_down_flag[hscs[txqm_id]][idx[txqm_id]]);
        for (entry = 0; entry < SYS_TMM_MAX_MAC_NUM_PER_TXQM; entry++)
        {    
            /* #1, calc index */
            index = DRV_INS(txqm_id, entry);

            /* #2, read HW table:  */
            tbl_id = McMacRxChanMap_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);        
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chanmap));

            /* ##2.1. calc step */
            val32 = 63;

            /* ##2.2. modify field value */
            /* ###2.2.1. */
            fld_id = McMacRxChanMap_chanMap_f;
            DRV_IOW_FIELD_NZ(lchip, tbl_id, fld_id, &val32, &rx_chanmap, txqm_id, 0);

            /* #3, write HW table: */
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &rx_chanmap));

        }
    }

    DP_DEBUG_FUNCTION_RETURN_PRINT();

    return CTC_E_NONE;
}
#endif

#if (SDB_MEM_MODEL != SDB_MODE)
STATIC int32
_sys_tmm_datapath_module_init(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 index = 0;
    uint32 value = 0;
    uint8  i = 0, j = 0;
    uint32 step = 0;
#ifndef EMULATION_ENV
    uint8  dp;
    uint32 entry_id = 0;
    EpePktProcFlexTunnelCtl_m epe_pkt;
    uint32 value_array[8];
#endif
    DP_DEBUG_FUNCTION_CALLED_PRINT();

    /*1. set init*/
    value = 1;

    for (i = 0; i < 2; i++)
    {
        index = DRV_INS(i, 0);
        cmd = DRV_IOW(NetRxInit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
    }

#ifdef PCS_IMG
    cmd = DRV_IOW(IpeShellInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
#endif

    for (i = 0; i < 2; i++)
    {
        index = DRV_INS(i, 0);
        cmd = DRV_IOW(BufRetrvDPInit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
    }

    cmd = DRV_IOW(BufRetrvShareInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(BufStoreProcInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    for (i = 0; i < 2; i++)
    {
        index = DRV_INS(i, 0);
        cmd = DRV_IOW(BufStoreDpCtlInit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
    }

    cmd = DRV_IOW(MetFifoProcInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(MetFifoShareInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

#ifdef PCS_IMG
    cmd = DRV_IOW(QMgrShellInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
#endif

    for (i = 0; i < 2; i++)
    {
        index = DRV_INS(i, 0);
        cmd = DRV_IOW(EpeScheduleInit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));

        cmd = DRV_IOW(NetTxInit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));

        cmd = DRV_IOW(NetRxInit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
    }

    cmd = DRV_IOW(IpeHdrAdjInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(IpeIntfMapInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(IpeLkupMgrInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(IpePktProcInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    /*for (i = 0; i < 3; i++)*/
    {
        index = DRV_INS(0, 0);
        cmd = DRV_IOW(ParserInit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
    }

    cmd = DRV_IOW(IpeFwdInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(DynamicAdInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(DynamicMiscKeyInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(EpeAclOamInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(EpeHdrAdjInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(EpeHdrProcInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(EpeNextHopInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrDeqChanInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrDeqL0Init_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrDeqL1Init_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrDeqL2Init_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrDeqL3Init_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrDeqL4CosInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrDeqL4GrpInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrDeqL4QueInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrDeqShpInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrErmInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrQWriteInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(EpeHdrEditInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(EpePktRewriteInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    for (i = 0; i < 8; i++)
    {
        index = DRV_INS(i, 0);
        cmd = DRV_IOW(McMacInit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));

        step = McMacStatsInit_quadSgmac1Init_f - McMacStatsInit_quadSgmac0Init_f;
        for (j = 0; j < 10; j++)
        {
            cmd = DRV_IOW(McMacStatsInit_t, (McMacStatsInit_quadSgmac0Init_f + step*j));
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &value));
        }
    }

    cmd = DRV_IOW(QuadSgmacInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    for (i = 0; i < 3; i++)
    {
        index = DRV_INS(i, 0);
        cmd = DRV_IOW(FlexDecodeInit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
    }

    cmd = DRV_IOW(MdioInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

#ifdef PCS_IMG
    for (i = 0; i < 1; i++)
#else
    for (i = 0; i < 2; i++)
#endif
    {
        index = DRV_INS(i, 0);

        cmd = DRV_IOW(LedInit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
    }

    cmd = DRV_IOW(I2CMasterInit0_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(I2CMasterInit1_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(OobFcInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(QMgrMsgMiscInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(DmaCtlInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(EcpuIntfInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    cmd = DRV_IOW(CpuMapInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

    /*for (i = 0; i < 7; i++)
    {
        index = DRV_INS(i, 0);
        cmd = DRV_IOW(McuIntfInit_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
        TSINGMA_DUMP_PRINT(g_tm_dump_fp, "write McuIntfInit 0 init 1 inst %d\n", i);
    }*/

    cmd = DRV_IOW(ScpuIntfInit_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));

#ifdef EMULATION_ENV
    sal_task_sleep(5000);
#else
    /*2. check init done */
    sal_task_sleep(1);

    if (0 == SDK_WORK_PLATFORM)
    {
        for (i = 0; i < 2; i++)
        {
            index = DRV_INS(i, 0);
            cmd = DRV_IOR(NetRxInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
            if (!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [NetRxInit.%d] Feature not initialized \n", i);
                return CTC_E_NOT_INIT;
            }
        }

        for (i = 0; i < 2; i++)
        {
            index = DRV_INS(i, 0);
            cmd = DRV_IOR(BufRetrvDPInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
            if (!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [BufRetrvDPInit.%d] Feature not initialized \n", i);
                return CTC_E_NOT_INIT;
            }
        }

        cmd = DRV_IOR(BufRetrvShareInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if (!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [BufRetrvShareInit] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(BufStoreProcInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if (!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [BufStoreProcInit] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        for (i = 0; i < 2; i++)
        {
            index = DRV_INS(i, 0);
            cmd = DRV_IOR(BufStoreDpCtlInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
            if (!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [BufStoreDpCtlInit.%d] Feature not initialized \n", i);
                return CTC_E_NOT_INIT;
            }
        }

        cmd = DRV_IOR(MetFifoProcInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if (!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [MetFifoProcInit] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(MetFifoShareInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if (!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [MetFifoShareInit] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        for (i = 0; i < 2; i++)
        {
            index = DRV_INS(i, 0);
            cmd = DRV_IOR(EpeScheduleInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
            if (!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [EpeScheduleInit.%d] Feature not initialized \n", i);
                return CTC_E_NOT_INIT;
            }

            cmd = DRV_IOR(NetTxInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
            if (!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [NetTxInit.%d] Feature not initialized \n", i);
                return CTC_E_NOT_INIT;
            }

            cmd = DRV_IOR(NetRxInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
            if (!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [NetRxInit.%d] Feature not initialized \n", i);
                return CTC_E_NOT_INIT;
            }
        }

        cmd = DRV_IOR(IpeHdrAdjInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [IpeHdrAdjInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(IpeIntfMapInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [IpeIntfMapInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(IpeLkupMgrInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [IpeLkupMgrInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(IpePktProcInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [IpePktProcInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(IpeFwdInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [IpeFwdInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(DynamicAdInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [DynamicAdInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(DynamicMiscKeyInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [DynamicMiscKeyInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(EpeAclOamInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [EpeAclOamInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(EpeHdrAdjInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [EpeHdrAdjInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(EpeHdrProcInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [EpeHdrProcInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(EpeNextHopInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [EpeNextHopInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrDeqChanInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrDeqChanInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrDeqL0InitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrDeqL0InitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrDeqL1InitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrDeqL1InitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrDeqL2InitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrDeqL2InitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrDeqL3InitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrDeqL3InitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrDeqL4CosInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrDeqL4CosInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrDeqL4GrpInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrDeqL4GrpInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrDeqL4QueInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrDeqL4QueInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrDeqShpInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrDeqShpInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrErmInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrErmInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrQWriteInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrQWriteInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(EpeHdrEditInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [EpeHdrEditInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(EpePktRewriteInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [EpePktRewriteInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        for (i = 0; i < 8; i++)
        {
            index = DRV_INS(i, 0);
            cmd = DRV_IOR(McMacInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
            if (!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [McMacInit.%d] Feature not initialized \n", i);
                return CTC_E_NOT_INIT;
            }

            cmd = DRV_IOR(McMacStatsInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, value_array));
            step = McMacStatsInitDone_quadSgmac1InitDone_f - McMacStatsInitDone_quadSgmac0InitDone_f;
            for (j = 0 ; j < 10; j++)
            {
                DRV_IOR_FIELD(lchip, McMacStatsInitDone_t, (McMacStatsInitDone_quadSgmac0InitDone_f + step*j), &value, value_array);
                if (!value)
                {
                    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [McMacStatsInit.%d field quadSgmac%dInit] Feature not initialized \n", i, j);
                    return CTC_E_NOT_INIT;
                }
            }
        }

        cmd = DRV_IOR(QuadSgmacInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QuadSgmacInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        for (i = 0; i < 3; i++)
        {
            index = DRV_INS(i, 0);
            cmd = DRV_IOR(FlexDecodeInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
            if (!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [FlexDecodeInitDone.%d] Feature not initialized \n", i);
                return CTC_E_NOT_INIT;
            }
        }

        index = 0;
        cmd = DRV_IOR(I2CMasterInitDone0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
        if (!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [I2CMasterInitDone0.%d] Feature not initialized \n", i);
            return CTC_E_NOT_INIT;
        }
        cmd = DRV_IOR(I2CMasterInitDone1_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
        if (!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [I2CMasterInitDone1.%d] Feature not initialized \n", i);
            return CTC_E_NOT_INIT;
        }

        for (i = 0; i < 2; i++)
        {
            index = DRV_INS(i, 0);
            cmd = DRV_IOR(LedInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
            if (!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [LedInitDone.%d] Feature not initialized \n", i);
                return CTC_E_NOT_INIT;
            }
        }

        cmd = DRV_IOR(OobFcInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [OobFcInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        cmd = DRV_IOR(QMgrMsgMiscInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [QMgrMsgMiscInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        /*special operation for wb reload: skip DmaCtlInitDone check in wb reload*/
        if(p_drv_master[lchip]->wb_status != DRV_WB_STATUS_RELOADING)
        {
            cmd = DRV_IOR(DmaCtlInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
            if(!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [DmaCtlInitDone.initDone]1 Feature not initialized \n");
                return CTC_E_NOT_INIT;
            }

            cmd = DRV_IOR(EcpuIntfInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
            if(!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [EcpuIntfInitDone.initDone] Feature not initialized \n");
                return CTC_E_NOT_INIT;
            }

            cmd = DRV_IOR(ScpuIntfInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
            if(!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [ScpuIntfInitDone.initDone] Feature not initialized \n");
                return CTC_E_NOT_INIT;
            }
        }

        cmd = DRV_IOR(CpuMapInitDone_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &value));
        if(!value)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [CpuMapInitDone.initDone] Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }

        /*for (i = 0; i < 7; i++)
        {
            index = DRV_INS(i, 0);
            cmd = DRV_IOR(McuIntfInitDone_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &value));
            if (!value)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, " [McuIntfInit.%d] Feature not initialized \n", i);
                return CTC_E_NOT_INIT;
            }
        }*/

        /*init done additional cfg*/

        /*QWriteCtl.cfgSingleBufferUnit write 432*/
        cmd = DRV_IOR(QWriteCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));
        value = 432;
        DRV_IOW_FIELD(lchip, QWriteCtl_t, QWriteCtl_cfgSingleBufferUnit_f, &value, value_array);
        cmd = DRV_IOW(QWriteCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));

        /*BufStoreMiscResrcCongestionStateCtl.totalBufCongestionThrd write 0x137fc*/
        for(dp = 0; dp < SYS_TMM_DP_NUM; dp++)
        {
            entry_id = DRV_INS(dp, 0);
            cmd = DRV_IOR(BufStoreMiscResrcCongestionStateCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, value_array));
            value = 0x137fc;
            DRV_IOW_FIELD(lchip, BufStoreMiscResrcCongestionStateCtl_t, 
                BufStoreMiscResrcCongestionStateCtl_totalBufCongestionThrd_f, &value, value_array);
            cmd = DRV_IOW(BufStoreMiscResrcCongestionStateCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, entry_id, cmd, value_array));
        }

        /*EpeAclOamCreditCtl.epeOamHashTrackCreditThrd write 15*/
        cmd = DRV_IOR(EpeAclOamCreditCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));
        value = 15;
        DRV_IOW_FIELD(lchip, EpeAclOamCreditCtl_t, EpeAclOamCreditCtl_epeOamHashTrackCreditThrd_f, &value, value_array);
        cmd = DRV_IOW(EpeAclOamCreditCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));

        /*IpeHdrAdjReserved.reserved write 0x8073*/
        cmd = DRV_IOR(IpeHdrAdjReserved_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));
        value = 0x8073;
        DRV_IOW_FIELD(lchip, IpeHdrAdjReserved_t, IpeHdrAdjReserved_reserved_f, &value, value_array);
        cmd = DRV_IOW(IpeHdrAdjReserved_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));

        /*QMgrMsgMiscDrainEnable.freePtrDrainEnable write 1*/
        cmd = DRV_IOR(QMgrMsgMiscDrainEnable_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));
        value = 1;
        DRV_IOW_FIELD(lchip, QMgrMsgMiscDrainEnable_t, QMgrMsgMiscDrainEnable_freePtrDrainEnable_f, &value, value_array);
        cmd = DRV_IOW(QMgrMsgMiscDrainEnable_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));

        /*EpePktProcFlexTunnelCtl.flexArray_[0~7]_flexHdrTemplate write 0*/
        cmd = DRV_IOR(EpePktProcFlexTunnelCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_pkt));
        value_array[0] = 0; //128bit 0
        value_array[1] = 0;
        value_array[2] = 0;
        value_array[3] = 0;
        DRV_IOW_FIELD(lchip, EpePktProcFlexTunnelCtl_t, EpePktProcFlexTunnelCtl_flexArray_0_flexHdrTemplate_f, value_array, &epe_pkt);
        DRV_IOW_FIELD(lchip, EpePktProcFlexTunnelCtl_t, EpePktProcFlexTunnelCtl_flexArray_1_flexHdrTemplate_f, value_array, &epe_pkt);
        DRV_IOW_FIELD(lchip, EpePktProcFlexTunnelCtl_t, EpePktProcFlexTunnelCtl_flexArray_2_flexHdrTemplate_f, value_array, &epe_pkt);
        DRV_IOW_FIELD(lchip, EpePktProcFlexTunnelCtl_t, EpePktProcFlexTunnelCtl_flexArray_3_flexHdrTemplate_f, value_array, &epe_pkt);
        DRV_IOW_FIELD(lchip, EpePktProcFlexTunnelCtl_t, EpePktProcFlexTunnelCtl_flexArray_4_flexHdrTemplate_f, value_array, &epe_pkt);
        DRV_IOW_FIELD(lchip, EpePktProcFlexTunnelCtl_t, EpePktProcFlexTunnelCtl_flexArray_5_flexHdrTemplate_f, value_array, &epe_pkt);
        DRV_IOW_FIELD(lchip, EpePktProcFlexTunnelCtl_t, EpePktProcFlexTunnelCtl_flexArray_6_flexHdrTemplate_f, value_array, &epe_pkt);
        DRV_IOW_FIELD(lchip, EpePktProcFlexTunnelCtl_t, EpePktProcFlexTunnelCtl_flexArray_7_flexHdrTemplate_f, value_array, &epe_pkt);
        cmd = DRV_IOW(EpePktProcFlexTunnelCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_pkt));

        /*IpeHeaderAdjustCpuChanCtl.fromCpuEn write 0*/
        sal_memset(value_array, 0, 8*sizeof(uint32));
        cmd = DRV_IOW(IpeHeaderAdjustCpuChanCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));

        /*OamParserCreditCtl.hdrAdjHdrEditCreditHighThrd write 47*/
        cmd = DRV_IOR(OamParserCreditCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));
        value = 47;
        DRV_IOW_FIELD(lchip, OamParserCreditCtl_t, OamParserCreditCtl_hdrAdjHdrEditCreditHighThrd_f, &value, value_array);
        cmd = DRV_IOW(OamParserCreditCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));

        /*RefDivSpnOamTxPulse.cfgRefDivSpnOamTxPulse write 0x500*/
        cmd = DRV_IOR(RefDivSpnOamTxPulse_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));
        value = 0x500;
        DRV_IOW_FIELD(lchip, RefDivSpnOamTxPulse_t, RefDivSpnOamTxPulse_cfgRefDivSpnOamTxPulse_f, &value, value_array);
        cmd = DRV_IOW(RefDivSpnOamTxPulse_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, value_array));
    }
#endif

    DP_DEBUG_FUNCTION_RETURN_PRINT();
        

    return CTC_E_NONE;
}
#endif 

int32
sys_tmm_datapath_serdes_clktree_cpumac_cfg(uint8 lchip, uint8 lane_id, uint8 mode)
{
    uint32 tbl_id = CpuMacClockTreeCfg_t;
    uint32 fld_id_base[] = {
        CpuMacClockTreeCfg_cfgClockHss20Tx0Sel_f,
        CpuMacClockTreeCfg_cfgClockHssL0TxDiv2Sel_f,
        CpuMacClockTreeCfg_cfgClockHssL0TxL2Div2Sel_f,
        CpuMacClockTreeCfg_cfgClockHssL0TxMultiLane_f,
        CpuMacClockTreeCfg_cfgHssL0Tx2RxLoopBackEn_f,
        CpuMacClockTreeCfg_cfgResetHss20Tx0Div_f,
        CpuMacClockTreeCfg_cfgResetHssL0TxDiv2_f,
        CpuMacClockTreeCfg_cfgHss20Tx0Divider_f,
        CpuMacClockTreeCfg_cfgHssTxDataOutSel0_f,
    };
    uint32 fld_id;
    uint32 fld_num = sizeof(fld_id_base) / sizeof(uint32);
    uint32 value[9][7] = {
       /*sgmii xfi   xlg   xxvg  lg    cg   2.5g*/
        {1,    0,    0,    0,    0,    0,   1   },  //CpuMacClockTreeCfg_cfgClockHss20Tx0Sel_f
        {0,    0,    0,    1,    1,    1,   0   },  //CpuMacClockTreeCfg_cfgClockHssL0TxDiv2Sel_f
        {0,    0,    0,    0,    0,    0,   0   },  //CpuMacClockTreeCfg_cfgClockHssL0TxL2Div2Sel_f
        {0,    0,    1,    0,    1,    1,   0   },  //CpuMacClockTreeCfg_cfgClockHssL0TxMultiLane_f
        {0,    0,    0,    0,    0,    0,   0   },  //CpuMacClockTreeCfg_cfgHssL0Tx2RxLoopBackEn_f
        {0,    1,    1,    1,    1,    1,   0   },  //CpuMacClockTreeCfg_cfgResetHss20Tx0Div_f
        {0,    1,    1,    0,    0,    0,   0   },  //CpuMacClockTreeCfg_cfgResetHssL0TxDiv2_f
        {4,    8,    8,    8,    8,    8,   2   },  //CpuMacClockTreeCfg_cfgHss20Tx0Divider_f
        {0,    2,    2,    3,    3,    3,   0   },  //CpuMacClockTreeCfg_cfgHssTxDataOutSel0_f
    };
    uint32 val_u32 = 0;
    uint32 fld_step[] = {
        CpuMacClockTreeCfg_cfgClockHss20Tx1Sel_f - CpuMacClockTreeCfg_cfgClockHss20Tx0Sel_f,
        CpuMacClockTreeCfg_cfgClockHssL1TxDiv2Sel_f - CpuMacClockTreeCfg_cfgClockHssL0TxDiv2Sel_f,
        CpuMacClockTreeCfg_cfgClockHssL1TxL2Div2Sel_f - CpuMacClockTreeCfg_cfgClockHssL0TxL2Div2Sel_f,
        CpuMacClockTreeCfg_cfgClockHssL1TxMultiLane_f - CpuMacClockTreeCfg_cfgClockHssL0TxMultiLane_f,
        CpuMacClockTreeCfg_cfgHssL1Tx2RxLoopBackEn_f - CpuMacClockTreeCfg_cfgHssL0Tx2RxLoopBackEn_f,
        CpuMacClockTreeCfg_cfgResetHss20Tx1Div_f - CpuMacClockTreeCfg_cfgResetHss20Tx0Div_f,
        CpuMacClockTreeCfg_cfgResetHssL1TxDiv2_f - CpuMacClockTreeCfg_cfgResetHssL0TxDiv2_f,
        CpuMacClockTreeCfg_cfgHss20Tx1Divider_f - CpuMacClockTreeCfg_cfgHss20Tx0Divider_f,
        CpuMacClockTreeCfg_cfgHssTxDataOutSel1_f - CpuMacClockTreeCfg_cfgHssTxDataOutSel0_f,
    };
    uint32 fld_idx;
    uint32 index = 0;
    uint32 cmd = 0;
    uint32 mode_idx = 0;
    CpuMacClockTreeCfg_m clk_tree;

    switch(mode)
    {
        case CTC_CHIP_SERDES_SGMII_MODE:
            mode_idx = 0;
            break;
        case CTC_CHIP_SERDES_XFI_MODE:
            mode_idx = 1;
            break;
        case CTC_CHIP_SERDES_XLG_MODE:
            mode_idx = 2;
            break;
        case CTC_CHIP_SERDES_XXVG_MODE:
            mode_idx = 3;
            break;
        case CTC_CHIP_SERDES_LG_MODE:
            mode_idx = 4;
            break;
        case CTC_CHIP_SERDES_CG_MODE:
            mode_idx = 5;
            break;
        case CTC_CHIP_SERDES_2DOT5G_MODE:
            mode_idx = 6;
            break;
        case CTC_CHIP_SERDES_NONE_MODE:
        default:
            return CTC_E_NONE;
    }

    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &clk_tree));
    for(fld_idx = 0; fld_idx < fld_num; fld_idx++)
    {
        /*CpuMacClockTreeCfg_cfgClockHssL0TxL2Div2Sel_f*/
        if(2 == fld_idx)
        {
            if(CTC_CHIP_SERDES_LG_MODE == mode)
            {
                if(2 <= lane_id)
                {
                    val_u32 = 1;
                    DRV_IOW_FIELD(lchip, tbl_id, CpuMacClockTreeCfg_cfgClockHssL2TxL2Div2Sel_f, &val_u32, &clk_tree);
                    DRV_IOW_FIELD(lchip, tbl_id, CpuMacClockTreeCfg_cfgClockHssL3TxL2Div2Sel_f, &val_u32, &clk_tree);
                }
                else
                {
                    val_u32 = 0;
                    DRV_IOW_FIELD(lchip, tbl_id, CpuMacClockTreeCfg_cfgClockHssL0TxL2Div2Sel_f, &val_u32, &clk_tree);
                    DRV_IOW_FIELD(lchip, tbl_id, CpuMacClockTreeCfg_cfgClockHssL1TxL2Div2Sel_f, &val_u32, &clk_tree);
                }
            }
            else if((CTC_CHIP_SERDES_XLG_MODE == mode) || (CTC_CHIP_SERDES_CG_MODE == mode))
            {
                val_u32 = 0;
                DRV_IOW_FIELD(lchip, tbl_id, CpuMacClockTreeCfg_cfgClockHssL0TxL2Div2Sel_f, &val_u32, &clk_tree);
                DRV_IOW_FIELD(lchip, tbl_id, CpuMacClockTreeCfg_cfgClockHssL1TxL2Div2Sel_f, &val_u32, &clk_tree);
                DRV_IOW_FIELD(lchip, tbl_id, CpuMacClockTreeCfg_cfgClockHssL2TxL2Div2Sel_f, &val_u32, &clk_tree);
                DRV_IOW_FIELD(lchip, tbl_id, CpuMacClockTreeCfg_cfgClockHssL3TxL2Div2Sel_f, &val_u32, &clk_tree);
            }
            else
            {
                fld_id = fld_id_base[fld_idx] + lane_id * fld_step[fld_idx];
                DRV_IOW_FIELD(lchip, tbl_id, fld_id, &(value[fld_idx][mode_idx]), &clk_tree);
            }
        }
        else
        {
            fld_id = fld_id_base[fld_idx] + lane_id * fld_step[fld_idx];
            DRV_IOW_FIELD(lchip, tbl_id, fld_id, &(value[fld_idx][mode_idx]), &clk_tree);
        }
    }
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &clk_tree));

    /*clktree reset*/
    tbl_id = CpuMacClockTreeCfg_t;
    
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &clk_tree));
    val_u32 = 1;
    fld_id = CpuMacClockTreeCfg_cfgResetHssL0TxDiv2_f + lane_id;
    DRV_IOW_FIELD(lchip, tbl_id, fld_id, &val_u32, &clk_tree);
    fld_id = CpuMacClockTreeCfg_cfgResetHss20Tx0Div_f + lane_id;
    DRV_IOW_FIELD(lchip, tbl_id, fld_id, &val_u32, &clk_tree);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &clk_tree));
    
    val_u32 = 0;
    fld_id = CpuMacClockTreeCfg_cfgResetHssL0TxDiv2_f + lane_id;
    DRV_IOW_FIELD(lchip, tbl_id, fld_id, &val_u32, &clk_tree);
    fld_id = CpuMacClockTreeCfg_cfgResetHss20Tx0Div_f + lane_id;
    DRV_IOW_FIELD(lchip, tbl_id, fld_id, &val_u32, &clk_tree);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &clk_tree));

    return CTC_E_NONE;
}

int32 
_sys_tmm_datapath_serdes_iddq_en(uint8 lchip, uint8 serdes_id, uint8 enable)
{
    uint8  lane_id  = 0;
    uint8  dp_id    = 0;
    uint8  txqm_id  = 0;
    uint8  step     = 0;
    uint32 index    = 0;
    uint32 cmd      = 0;
    uint32 tbl_id   = 0;
    uint32 field_id = 0;
    uint32 value    = enable ? 1 : 0;

    /*CPUMAC IDDQ Configure*/
    if(SYS_TMM_CPUMAC_SERDES_START_ID <= serdes_id)
    {
        tbl_id   = CpuMacHssIddqEnable_t;
        field_id = CpuMacHssIddqEnable_hssIddq0En_f + (serdes_id % 4);

        cmd = DRV_IOW(tbl_id, field_id);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &value));
    }
    /*NW IDDQ Configure*/
    else
    {
        dp_id = SYS_TMM_GET_DP_ID_FROM_SERDES(serdes_id);
        SYS_TMM_GET_TXQM_BY_SERDES(serdes_id, txqm_id);

        lane_id  = SYS_TMM_IS_PCS_X16(txqm_id) ? (serdes_id % 16) : (serdes_id % 8);
        step     = (Dp1Mac0HssIddqEnable_t - Dp0Mac0HssIddqEnable_t) * dp_id;
        tbl_id   = Dp0Mac0HssIddqEnable_t + step + (txqm_id % 4);
        field_id = Dp0Mac0HssIddqEnable_hssIddq0En_f + lane_id;

        cmd = DRV_IOW(tbl_id, field_id);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &value));
    }
    
    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_init_serdes_fw_load_chk(uint8 lchip, uint8 hss_idx, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
    uint8 stat = 0;
    uint8 physic_serdes_id = 0;
    uint8 serdes_end = 0;
    uint8 logic_serdes_id = 0;

    TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "\n\n %s Start \n\n", __FUNCTION__);

    if (p_drv_master[lchip]->wb_status == DRV_WB_STATUS_RELOADING)
    {
        return CTC_E_NONE;
    }

    serdes_end = (SYS_TMM_CPUMAC_HSS_ID == hss_idx ? (SYS_TMM_MAX_SERDES_NUM + SYS_TMM_CPUMAC_SERDES_NUM) : \
                                           ((hss_idx + 1) * SYS_TMM_LANE_NUM_PER_HSS));

    for(physic_serdes_id = hss_idx * SYS_TMM_LANE_NUM_PER_HSS; physic_serdes_id < serdes_end; physic_serdes_id ++)
    {
        _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, physic_serdes_id, &logic_serdes_id);
        SYS_CONDITION_CONTINUE(MCHIP_CAP(SYS_CAP_DMPS_SERDES_NUM_PER_SLICE) <= logic_serdes_id);
        SYS_CONDITION_CONTINUE(SYS_TMM_IS_SERDES_ABANDON(p_datapath_cfg->serdes[logic_serdes_id].mode, 
                                     p_datapath_cfg->serdes[logic_serdes_id].is_dynamic));

        CTC_ERROR_RETURN(sys_tmm_serdes_is_correct_fw_loaded(lchip, physic_serdes_id, &stat));
        TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "\n\n stat %d \n\n", stat);
        if(0 == stat)
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% SerDes %d FW is not already loaded. Status %d\n", physic_serdes_id, stat);
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%% SerDes %d FW is not already loaded. Status %d\n", physic_serdes_id, stat);
            return CTC_E_HW_FAIL;
        }
    }

    TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "\n\n %s End \n\n", __FUNCTION__);

    return CTC_E_NONE;
}

int32 _sys_tmm_datapath_init_serdes_cfg(uint8 lchip, uint8 hss_idx, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
    uint8 physic_serdes_id = 0;
    uint8 serdes_end = 0;
    uint8 logic_serdes_id = 0;

    if (p_drv_master[lchip]->wb_status == DRV_WB_STATUS_RELOADING)
    {
        return CTC_E_NONE;
    }

    TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "\n\n %s Start \n\n", __FUNCTION__);
    
    serdes_end = (SYS_TMM_CPUMAC_HSS_ID == hss_idx ? (SYS_TMM_MAX_SERDES_NUM + SYS_TMM_CPUMAC_SERDES_NUM) : \
                                       ((hss_idx + 1) * SYS_TMM_LANE_NUM_PER_HSS));

    for(physic_serdes_id = hss_idx * SYS_TMM_LANE_NUM_PER_HSS; physic_serdes_id < serdes_end; physic_serdes_id ++)
    {
        SYS_CONDITION_CONTINUE(CTC_E_NONE != _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, physic_serdes_id, &logic_serdes_id));
        SYS_CONDITION_CONTINUE(MCHIP_CAP(SYS_CAP_DMPS_SERDES_NUM_PER_SLICE) <= logic_serdes_id);
        SYS_CONDITION_CONTINUE(SYS_TMM_IS_SERDES_ABANDON(p_datapath_cfg->serdes[logic_serdes_id].mode, 
                                     p_datapath_cfg->serdes[logic_serdes_id].is_dynamic));

        CTC_ERROR_RETURN(sys_tmm_serdes_init(lchip, physic_serdes_id, p_datapath_cfg->serdes[logic_serdes_id].mode));
        /*set RX polarity*/
        CTC_ERROR_RETURN(sys_tmm_serdes_set_polarity(lchip, physic_serdes_id, 0, p_datapath_cfg->serdes[logic_serdes_id].rx_polarity));
        /*set TX polarity*/
        CTC_ERROR_RETURN(sys_tmm_serdes_set_polarity(lchip, physic_serdes_id, 1, p_datapath_cfg->serdes[logic_serdes_id].tx_polarity));
    }

    TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "\n\n %s End \n\n", __FUNCTION__);
    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_init_presetN(uint8 lchip, uint8 hss_idx)
{
    uint32 cmd = 0;
    uint32 index = 0;
    uint32 value;
    uint8 lane_id;
    uint32 tbl_list[3] = {HssOctal0Cfg_t, HssOctal1Cfg_t, HssOctalCfg_t};
    uint32 tbl_idx = 0;
    uint8 ctcxs_id = 0;
    uint8 is_ctchs = 0;
    uint8 step = 0;
    uint32 field_id = 0;
    sys_datapath_hss_attribute_t* p_hss_vec = NULL;
    CpuMacHssQuadCfg_m    hss_q_cfg;
    HssOctalCfg_m         hss_oct_cfg;

    TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "\n%s Start \n", __FUNCTION__);

    if(SYS_TMM_CPUMAC_HSS_ID == hss_idx)
    {
        /*cpumac serdes config*/       
        /*cfg CpuMacHssQuadCfg.cfgHssQuadGlueRst = 0*/
        /*cfg CpuMacHssQuadCfg.cfgHssQuadRegAccRst = 0*/
        cmd = DRV_IOR(CpuMacHssQuadCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hss_q_cfg));
        value = 0;
        DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuadGlueRst_f, &value, &hss_q_cfg);
        DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuadRegAccRst_f, &value, &hss_q_cfg);
        /*cfg CpuMacHssQuadCfg.cfgHssQuad_0~3_cfgHssApbResetBar = 0*/
        value = 1;
        DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuad_0_cfgHssApbResetBar_f, &value, &hss_q_cfg);
        DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuad_1_cfgHssApbResetBar_f, &value, &hss_q_cfg);
        DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuad_2_cfgHssApbResetBar_f, &value, &hss_q_cfg);
        DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuad_3_cfgHssApbResetBar_f, &value, &hss_q_cfg);
        /*cfg CpuMacHssQuadCfg.cfgHssQuad_0~3_cfgHssRxReadyGate = 2    phy ready & sigdet*/
        value = 2;
        DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuad_0_cfgHssRxReadyGate_f, &value, &hss_q_cfg);
        DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuad_1_cfgHssRxReadyGate_f, &value, &hss_q_cfg);
        DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuad_2_cfgHssRxReadyGate_f, &value, &hss_q_cfg);
        DRV_IOW_FIELD(lchip, CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuad_3_cfgHssRxReadyGate_f, &value, &hss_q_cfg);
        cmd = DRV_IOW(CpuMacHssQuadCfg_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hss_q_cfg));

        /*cpumac clock tree config*/
        p_hss_vec = ctc_vector_get(p_usw_datapath_master[lchip]->p_hss_vector, SYS_TMM_CPUMAC_HSS_ID);

        if(NULL == p_hss_vec)
        {
            return CTC_E_NONE;
        }
        for(lane_id = 0; lane_id < SYS_TMM_CPUMAC_SERDES_NUM; lane_id++)
        {
            CTC_ERROR_RETURN(sys_tmm_datapath_serdes_clktree_cpumac_cfg(lchip, lane_id, p_hss_vec->serdes_info[lane_id].mode));
        }
    }
    else
    {
        /*normal network port apb access configure*/
        SYS_TMM_GET_CTCXS_ID_BY_HSS_ID(hss_idx, ctcxs_id, is_ctchs);
        index = DRV_INS(ctcxs_id, 0);

        if(is_ctchs)
        {
            tbl_idx = hss_idx % 2;  
        }
        else
        {
            tbl_idx = 2;
        }
        cmd = DRV_IOR(tbl_list[tbl_idx], DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hss_oct_cfg));
        value = 0;
        DRV_IOW_FIELD(lchip, tbl_list[tbl_idx], HssOctalCfg_cfgHssOctalGlueRst_f, &value, &hss_oct_cfg);
        DRV_IOW_FIELD(lchip, tbl_list[tbl_idx], HssOctalCfg_cfgHssOctalRegAccRst_f, &value, &hss_oct_cfg);
        
        for(lane_id = 0; lane_id < SYS_TMM_LANE_NUM_PER_HSS; lane_id ++)
        {
            value = 1;
            step = HssOctal0Cfg_cfgHssOctal0_1_cfgHssApbResetBar_f - HssOctal0Cfg_cfgHssOctal0_0_cfgHssApbResetBar_f;
            field_id = HssOctal0Cfg_cfgHssOctal0_0_cfgHssApbResetBar_f + lane_id*step;
            DRV_IOW_FIELD(lchip, tbl_list[tbl_idx], field_id, &value, &hss_oct_cfg);
            /*cfg RxReadyGate = 2    phy ready & sigdet*/
            value = 0x2;
            step = HssOctal0Cfg_cfgHssOctal0_1_cfgHssRxReadyGate_f - HssOctal0Cfg_cfgHssOctal0_0_cfgHssRxReadyGate_f;
            field_id = HssOctal0Cfg_cfgHssOctal0_0_cfgHssRxReadyGate_f + lane_id*step;
            DRV_IOW_FIELD(lchip, tbl_list[tbl_idx], field_id, &value, &hss_oct_cfg);
        }
        cmd = DRV_IOW(tbl_list[tbl_idx], DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hss_oct_cfg));
    }

    TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "%s End \n", __FUNCTION__);
    return CTC_E_NONE;
}

/*
init_flag[N]: TRUE - HSS N need init  FALSE - skip HSS N init
The HSS skip init when:
--all lane in this octal group is abandoned
--and (HSS id is not 1/3/4/6/9/10, or HSS is 1/3/4/6 and all HS lanes are abandoned, or HSS is 9/10 and all CS lanes are abandoned)
*/
int32
_sys_tmm_datapath_init_get_hss_init_flag(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg, uint8 init_flag[])
{
    uint8  hss_id;
    uint8  lane_id;
    uint8  idx;
    uint8  hs_cnt = 0;
    uint8  cs_cnt = 0;
    uint16 chk_hss_bmp = 0x069a;  //0b 011010 011010
    ctc_datapath_serdes_prop_t* p_serdes = NULL;

    SYS_CONDITION_RETURN(((NULL == p_datapath_cfg) || (NULL == init_flag)), CTC_E_INVALID_PTR);

    p_serdes = p_datapath_cfg->serdes;
    for(hss_id = 0; hss_id < SYS_TMM_CPUMAC_HSS_ID+1; hss_id++)
    {
        if((DRV_CHIP_SUB_TYPE_4 == DRV_CHIP_SUB_TYPE(lchip)) && DRV_IS_TMM(lchip) && 
           ((3 >= hss_id) || ((6 <= hss_id) && (9 >= hss_id))))
        {
            init_flag[hss_id] = FALSE;
            continue;
        }
        init_flag[hss_id] = ((chk_hss_bmp >> hss_id) & 0x1) ? FALSE : TRUE;
        for(lane_id = 0; lane_id < SYS_TMM_LANE_NUM_PER_HSS; lane_id ++)
        {
            idx = SYS_TMM_GET_SERDES_ID_BY_LANE(hss_id, lane_id);
            SYS_CONDITION_CONTINUE(idx >= MCHIP_CAP(SYS_CAP_DMPS_SERDES_NUM_PER_SLICE));
            if(!SYS_TMM_IS_SERDES_ABANDON(p_serdes[idx].mode, p_serdes[idx].is_dynamic) &&
                (CTC_DATAPATH_SERDES_NUM > p_serdes[idx].physical_serdes_id))
            {
                init_flag[hss_id] = TRUE;
                if((3 >= hss_id) || ((6 <= hss_id) && (9 >= hss_id)))
                {
                    hs_cnt++;
                }
                else
                {
                    cs_cnt++;
                }
                break;
            }
        }
    }

    if(0 == hs_cnt)
    {
        init_flag[0]  = FALSE;
        init_flag[1]  = FALSE;
        init_flag[2]  = FALSE;
        init_flag[3]  = FALSE;
        init_flag[6]  = FALSE;
        init_flag[7]  = FALSE;
        init_flag[8]  = FALSE;
        init_flag[9]  = FALSE;
    }
    if(0 == cs_cnt)
    {
        init_flag[4]  = FALSE;
        init_flag[5]  = FALSE;
        init_flag[10] = FALSE;
        init_flag[11] = FALSE;
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_init_serdes_rlfclk_chain_cfg(uint8 lchip, uint8 hss_idx)
{
    uint8 serdes_id = 0;
    uint8 serdes_end = 0;
    uint16 data = 0;
    uint16 val_list[4][2] = {
        /*00CA    00C9*/
        {0x0001,  0x0331},  /*Top*/
        {0x0001,  0x0391},  /*Bottom*/
        {0x0001,  0x00DC},  /*Left*/
        {0x0001,  0x0391}   /*Right*/
    };
    
    /*Top: 0  Bottom: 1  Left: 2  Right:3*/
    uint8 dir_list[SYS_TMM_MAX_SERDES_NUM + SYS_TMM_CPUMAC_SERDES_NUM] = {
        0, 0, 0, 0, 0, 0, 0, 0,    /*MAC0DP0*/
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0,    /*MAC1DP0*/
        0, 0, 0, 0, 0, 0, 0, 0, 
        1, 1, 1, 3, 1, 1, 1, 2,    /*MAC2DP0*/
        1, 1, 1, 2, 1, 1, 1, 3,    /*MAC3DP0*/
        0, 0, 0, 0, 0, 0, 0, 0,    /*MAC0DP1*/
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0,    /*MAC1DP1*/
        0, 0, 0, 0, 0, 0, 0, 0, 
        1, 1, 1, 3, 1, 1, 1, 2,    /*MAC3DP1*/
        1, 1, 1, 2, 1, 1, 1, 3,    /*MAC3DP1*/
        3, 1, 2, 1          /*CPUMAC*/   
    };

    TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "\n %s Start \n\n", __FUNCTION__);

    serdes_end = (SYS_TMM_CPUMAC_HSS_ID == hss_idx ? (SYS_TMM_MAX_SERDES_NUM + SYS_TMM_CPUMAC_SERDES_NUM) : \
                                               ((hss_idx + 1) * SYS_TMM_LANE_NUM_PER_HSS));

    for(serdes_id = hss_idx * SYS_TMM_LANE_NUM_PER_HSS; serdes_id < serdes_end; serdes_id ++)
    {
        data = val_list[dir_list[serdes_id]][0];
        CTC_ERROR_RETURN(sys_tmm_serdes_write_reg(lchip, serdes_id, 0xca, 0x0, data));
        data = val_list[dir_list[serdes_id]][1];
        CTC_ERROR_RETURN(sys_tmm_serdes_write_reg(lchip, serdes_id, 0xc9, 0x0, data));
    }
    
    TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "\n %s End \n\n", __FUNCTION__);

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_init_serdes(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
#ifndef EMULATION_ENV
    uint8 lane_id = 0;
    uint8 serdes_id = 0;
    uint8 hss_idx = 0;
    uint8 lane_num = 0;
    uint8 logic_serdes_id = 0;
    uint16 bit_map = 0x1013;
    uint8 hss_init_flag[SYS_TMM_CPUMAC_HSS_ID+1] = {0};
    uint8  hss_is_valid[SYS_TMM_CPUMAC_HSS_ID+1] = {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE};

    if(DRV_CHIP_SUB_TYPE_4 == DRV_CHIP_SUB_TYPE(lchip))
    {
        hss_is_valid[0] = FALSE;
        hss_is_valid[1] = FALSE;
        hss_is_valid[2] = FALSE;
        hss_is_valid[3] = FALSE;
        hss_is_valid[6] = FALSE;
        hss_is_valid[7] = FALSE;
        hss_is_valid[8] = FALSE;
        hss_is_valid[9] = FALSE;
    }

    /*char T2[256];
    time_t curr_time;
    struct tm *current_time;
    struct timeval current;*/
#endif

    TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "\n\n %s Start \n\n", __FUNCTION__);

    CTC_ERROR_RETURN(sys_tmm_serdes_init_fw_header(lchip));

#ifndef EMULATION_ENV
    CTC_ERROR_RETURN(_sys_tmm_datapath_init_get_hss_init_flag(lchip, p_datapath_cfg, hss_init_flag));

    for(hss_idx = 0; hss_idx <= SYS_TMM_CPUMAC_HSS_ID; hss_idx ++)
    {    
        if(((bit_map >> hss_idx) & 0x1)== 0)
        {
            /*continue;*/
        }
        
        lane_num = (hss_idx == SYS_TMM_CPUMAC_HSS_ID) ? SYS_TMM_CPUMAC_SERDES_NUM : SYS_TMM_LANE_NUM_PER_HSS;
        
        TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "\n\n HSS-IDX %d  Init Start \n\n", hss_idx );

        for(lane_id = 0; lane_id < lane_num; lane_id ++)
        {
            serdes_id = hss_idx * SYS_TMM_LANE_NUM_PER_HSS + lane_id;
            TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "SerDes Id %d Mode : %d\n", serdes_id, p_datapath_cfg->serdes[serdes_id].mode);
        }

        /*1. Release IDQ*/
        /*1.1 check */
        SYS_CONDITION_CONTINUE(FALSE == hss_init_flag[hss_idx]);

        /*1.2 Release IDQ*/
        TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "Release IDDQ\n");
        for(lane_id = 0; lane_id < lane_num; lane_id ++)
        {
            serdes_id = hss_idx * SYS_TMM_LANE_NUM_PER_HSS + lane_id;
            CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_iddq_en(lchip, serdes_id, FALSE));
        }

        /*2. PresetN */
        CTC_ERROR_RETURN(_sys_tmm_datapath_init_presetN(lchip, hss_idx));

        /*3. All Reset*/
        TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "All Reset\n");
        for(lane_id = 0; lane_id < lane_num; lane_id ++)
        {
            serdes_id = hss_idx * SYS_TMM_LANE_NUM_PER_HSS + lane_id;
            
            CTC_ERROR_RETURN(sys_tmm_serdes_set_domain_reset(lchip, serdes_id, SYS_TMM_SERDES_SOFT_RESET));
        }
        /*20201117: delay 10ms after domain reset to ensure FW load ready. not a precise value.*/
        sal_task_sleep(10);

        /*4. RefClk Chain cfg*/
        CTC_ERROR_RETURN(_sys_tmm_datapath_init_serdes_rlfclk_chain_cfg(lchip, hss_idx));
    }

    /*curr_time = time(NULL);
    current_time = localtime(&curr_time);
    gettimeofday(&current, NULL);
    sal_sprintf(T2, "[(%d-%d-%d)%02dh%02dm%02ds-%ldus]", current_time->tm_year + 1900,current_time->tm_mon + 1, current_time->tm_mday,current_time->tm_hour,current_time->tm_min,current_time->tm_sec,current.tv_usec);
    sal_printf("Before: %s; \n",  T2);*/

    /*5. Load SerDes Firmware for all 100 lanes*/
    if(1 != SDK_WORK_PLATFORM && (!sys_usw_chip_get_reset_hw_en(lchip)))
    {
        CTC_ERROR_RETURN(sys_tmm_mcu_serdes_loading(lchip, hss_init_flag));
    }

    /*curr_time = time(NULL);
    current_time = localtime(&curr_time);
    gettimeofday(&current, NULL);
    sal_sprintf(T2, "[(%d-%d-%d)%02dh%02dm%02ds-%ldus]", current_time->tm_year + 1900,current_time->tm_mon + 1, current_time->tm_mday,current_time->tm_hour,current_time->tm_min,current_time->tm_sec,current.tv_usec);
    sal_printf("After: %s; \n",  T2);*/
    
    /*6. Power Down and disable TX*/
    for(hss_idx = 0; hss_idx <= SYS_TMM_CPUMAC_HSS_ID; hss_idx ++)
    {
        SYS_CONDITION_CONTINUE(FALSE == hss_init_flag[hss_idx]);
        SYS_CONDITION_CONTINUE(FALSE == hss_is_valid[hss_idx]);
        lane_num = (hss_idx == SYS_TMM_CPUMAC_HSS_ID) ? SYS_TMM_CPUMAC_SERDES_NUM : SYS_TMM_LANE_NUM_PER_HSS;
        for(lane_id = 0; lane_id < lane_num; lane_id ++)
        {
            serdes_id = hss_idx * SYS_TMM_LANE_NUM_PER_HSS + lane_id;
            _sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, serdes_id, &logic_serdes_id);

            CTC_ERROR_RETURN(sys_tmm_serdes_set_tx_en(lchip, serdes_id, FALSE));

            if((SYS_TMM_USELESS_ID8 == logic_serdes_id) || SYS_TMM_IS_MODE_NONE(p_datapath_cfg->serdes[logic_serdes_id].mode))
            {
                CTC_ERROR_RETURN(sys_tmm_serdes_set_power_en(lchip, serdes_id, FALSE));
                continue;
            }
        }
    }
    
    /*7. check firmware Load*/
    /*8. SerDes Init Configure*/
    if (1 != SDK_WORK_PLATFORM)
    {
        if(!sys_usw_chip_get_reset_hw_en(lchip))
        {
            sal_task_sleep(500);
        }
        for(hss_idx = 0; hss_idx <= SYS_TMM_CPUMAC_HSS_ID; hss_idx ++)
        {
            SYS_CONDITION_CONTINUE(FALSE == hss_init_flag[hss_idx]);
            SYS_CONDITION_CONTINUE(FALSE == hss_is_valid[hss_idx]);
            if(1 != SDK_WORK_PLATFORM  && (!sys_usw_chip_get_reset_hw_en(lchip)))
            {
                CTC_ERROR_RETURN(_sys_tmm_datapath_init_serdes_fw_load_chk(lchip, hss_idx, p_datapath_cfg));
            }
            CTC_ERROR_RETURN(_sys_tmm_datapath_init_serdes_cfg(lchip, hss_idx, p_datapath_cfg));      
            TSINGMA_DUMP_PRINT(g_tmm_serdes_init_dump_fp, "\n\n HSS-IDX %d  Init End \n\n", hss_idx);
        }
    }

#endif

    return CTC_E_NONE;
}

/**
@brief packet buffer init
*/
#if (SDB_MEM_MODEL != SDB_MODE)
STATIC int32
_sys_tmm_datapath_packet_buffer_init(uint8 lchip)
{
    uint8 index = 0;
    uint8 step = 0;
    uint8 fail_cnt = 0;
    uint32 tbl_id = 0;
    uint32 val = 0;
    uint32 cmd = 0;
    ds1_t ds;
    uint8 tbl_index = 0;

    /* 
    bit 128-131 HsFail don't care, bit 144-151 packet buffer bank failure, at most only 1bit could be 1
    if set to 1, need configure corresponding packet buffer bank disable.
    */
    drv_read_efuse_data(lchip, 4, 1, &val);
    val = val >> SYS_USW_PACKET_BUFFER_BANK_OFFSET;
    for (index = 0; index < SYS_USW_PACKET_BUFFER_BANK_CNT; index++)
    {
        if (!CTC_IS_BIT_SET(val, index))
        {
            continue;
        }
        fail_cnt++;
        tbl_index = index;
    }
    if (fail_cnt > SYS_USW_PACKET_BUFFER_BANK_FAIL_CNT_MAX)
    {
        return CTC_E_HW_FAIL;
    }
    /* 
    if packet buffer bank failure is 0, in order to make sure the consistency of
    total buffer size, set the last bank can't be used.
    */
    tbl_index = ((0 == fail_cnt)?  (index - 1): tbl_index);
    /* chip default value is 1 need configure to 0 */
    sal_memset(ds, 0 ,sizeof(ds));
    cmd = DRV_IOR(BufStoreProcGetPtrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    SetBufStoreProcGetPtrCtl(V, freePtrGetUseRandomEn_f, &ds, 0);
    cmd = DRV_IOW(BufStoreProcGetPtrCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));

    step = BufStoreFreeList1CntCtl_t - BufStoreFreeList0CntCtl_t;
    tbl_id = BufStoreFreeList0CntCtl_t + step * tbl_index;
    sal_memset(ds, 0 ,sizeof(ds));
    cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    SetBufStoreFreeList0CntCtl(V, freeListRam0MinBufCnt_f, &ds, 0xfff);
    cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    
    /* chip default value is 1 need configure to 0 */
    step = BufStoreFreeListLoadEn_loadFreeListRam1IntfFifoEn_f - BufStoreFreeListLoadEn_loadFreeListRam0IntfFifoEn_f;
    sal_memset(ds, 0 ,sizeof(ds));
    cmd = DRV_IOR(BufStoreFreeListLoadEn_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    SetBufStoreFreeListLoadEn(V, loadFreeListRam0IntfFifoEn_f + step * tbl_index, &ds, 0);
    cmd = DRV_IOW(BufStoreFreeListLoadEn_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));

    return CTC_E_NONE;
}
#endif

int32
sys_tmm_datapath_init_macpcs_power_down(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
    uint32 index  = 0;
    uint32 tbl_id;
    uint32 cmd;
    uint32 value = 0;
    uint8  logic_serdes_id;
    uint8  dp = 0; /*dp id 0~1*/
    uint8  hscs = 0; /*hs or cs, 0-hs, 1-cs*/
    uint8  hscs_idx = 0; /*hs or cs index, 0~3*/
    //uint8  dp_down_flag[SYS_TMM_DP_NUM] = {TRUE, TRUE};  /*if current dp need power down, TRUE-do power down*/
    uint8  cm_down_flag = TRUE; /*if cpumac need power down, TRUE-do power down*/
    uint8  flexe_down_flag[SYS_TMM_DP_NUM] = {TRUE, TRUE}; /*if current dp flexe need power down, TRUE-do power down*/
    ctc_datapath_serdes_prop_t *p_serdes = p_datapath_cfg->serdes;

    CtcHsCtlEnClk_m hs_en;
    CtcCsCtlEnClk_m cs_en;
    CtcFlexeCrossCtlEnClk_m fc_en;
    CtcFlexeShimCtlEnClk_m fs_en;
    /*CtcDpTxCtlClockEn_m dp_tx_en;
    CtcDpRxCtlClockEn_m dp_rx_en;*/
    CpuMacCtlEnClk_m cm_en;

    p_usw_datapath_master[lchip]->hscs_down_flag[0][0] = TRUE;
    p_usw_datapath_master[lchip]->hscs_down_flag[0][1] = TRUE;
    p_usw_datapath_master[lchip]->hscs_down_flag[0][2] = TRUE;
    p_usw_datapath_master[lchip]->hscs_down_flag[0][3] = TRUE;
    p_usw_datapath_master[lchip]->hscs_down_flag[1][0] = TRUE;
    p_usw_datapath_master[lchip]->hscs_down_flag[1][1] = TRUE;
    p_usw_datapath_master[lchip]->hscs_down_flag[1][2] = TRUE;
    p_usw_datapath_master[lchip]->hscs_down_flag[1][3] = TRUE;

    /*0~95*/
    for(logic_serdes_id = 0; logic_serdes_id < SYS_TMM_MAX_SERDES_NUM; logic_serdes_id++)
    {
        dp = SYS_TMM_GET_DP_ID_FROM_SERDES(logic_serdes_id);

        if(16 > logic_serdes_id)
        {
            hscs = 0;
            hscs_idx = 0;
        }
        else if(32 > logic_serdes_id)
        {
            hscs = 0;
            hscs_idx = 1;
        }
        else if(40 > logic_serdes_id)
        {
            hscs = 1;
            hscs_idx = 0;
        }
        else if(48 > logic_serdes_id)
        {
            hscs = 1;
            hscs_idx = 1;
        }
        else if(64 > logic_serdes_id)
        {
            hscs = 0;
            hscs_idx = 2;
        }
        else if(80 > logic_serdes_id)
        {
            hscs = 0;
            hscs_idx = 3;
        }
        else if(88 > logic_serdes_id)
        {
            hscs = 1;
            hscs_idx = 2;
        }
        else
        {
            hscs = 1;
            hscs_idx = 3;
        }

        if((!SYS_TMM_IS_MODE_NONE(p_serdes[logic_serdes_id].mode)) || (0 != p_serdes[logic_serdes_id].is_dynamic))
        {
            if(TRUE == p_usw_datapath_master[lchip]->hscs_down_flag[hscs][hscs_idx])
            {
                p_usw_datapath_master[lchip]->hscs_down_flag[hscs][hscs_idx] = FALSE;
            }
            /*if(TRUE == dp_down_flag[dp])
            {
                dp_down_flag[dp] = FALSE;
            }*/
        }
    }

    if((TRUE != p_usw_datapath_master[lchip]->hscs_down_flag[1][2]) || (TRUE != p_usw_datapath_master[lchip]->hscs_down_flag[1][3]))
    {
        flexe_down_flag[1] = FALSE;
    }

    if((TRUE != p_usw_datapath_master[lchip]->hscs_down_flag[1][0]) || (TRUE != p_usw_datapath_master[lchip]->hscs_down_flag[1][1]))
    {
        flexe_down_flag[0] = FALSE;
    }

    /*96~99 cpumac*/
    for(logic_serdes_id = SYS_TMM_MAX_SERDES_NUM; logic_serdes_id < MCHIP_CAP(SYS_CAP_DMPS_SERDES_NUM_PER_SLICE); logic_serdes_id++)
    {
        if((!SYS_TMM_IS_MODE_NONE(p_serdes[logic_serdes_id].mode)) || (0 != p_serdes[logic_serdes_id].is_dynamic))
        {
            cm_down_flag = FALSE;
        }
    }
    /*for 24Q+4SGMII, epe calendar in dp 1 is needed, but power down cfg will lead to access fail, so keep dp1 power up*/
    /*if(dp_down_flag[0])
    {
        if(((!SYS_TMM_IS_MODE_NONE(p_serdes[96].mode)) || (0 != p_serdes[96].is_dynamic)) || 
           ((!SYS_TMM_IS_MODE_NONE(p_serdes[97].mode)) || (0 != p_serdes[97].is_dynamic)))
        {
            dp_down_flag[0] = FALSE;
        }
    }
    if(dp_down_flag[1])
    {
        if(((!SYS_TMM_IS_MODE_NONE(p_serdes[98].mode)) || (0 != p_serdes[98].is_dynamic)) || 
           ((!SYS_TMM_IS_MODE_NONE(p_serdes[99].mode)) || (0 != p_serdes[99].is_dynamic)))
        {
            if((CTC_CHIP_SERDES_XLG_MODE != p_serdes[98].mode) && (CTC_CHIP_SERDES_CG_MODE != p_serdes[98].mode))
            {
                dp_down_flag[1] = FALSE;
            }
        }
    }*/

    /*CtcHsCtlEnClk*/
    for(hscs_idx = 0; hscs_idx < 4; hscs_idx++)
    {
        SYS_CONDITION_CONTINUE(FALSE == p_usw_datapath_master[lchip]->hscs_down_flag[0][hscs_idx]);

        index = DRV_INS(hscs_idx, 0);

        tbl_id = CtcHsCtlEnClk_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hs_en));
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcHsCtlEnClk_enClkMcu_f, &value, &hs_en, hscs_idx, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcHsCtlEnClk_enClkMcuIntf_f, &value, &hs_en, hscs_idx, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcHsCtlEnClk_enClkMcFec_f, &value, &hs_en, hscs_idx, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcHsCtlEnClk_enClkMcMac_f, &value, &hs_en, hscs_idx, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcHsCtlEnClk_enClkMcPcs_f, &value, &hs_en, hscs_idx, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcHsCtlEnClk_enClkMcHata_f, &value, &hs_en, hscs_idx, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hs_en));
    }

    /*CtcCsCtlEnClk*/
    for(hscs_idx = 0; hscs_idx < 4; hscs_idx++)
    {
        SYS_CONDITION_CONTINUE(FALSE == p_usw_datapath_master[lchip]->hscs_down_flag[1][hscs_idx]);

        index = DRV_INS(hscs_idx, 0);

        tbl_id = CtcCsCtlEnClk_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cs_en));
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcCsCtlEnClk_enClkMcFec_f, &value, &cs_en, hscs_idx, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcCsCtlEnClk_enClkMcMac_f, &value, &cs_en, hscs_idx, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcCsCtlEnClk_enClkMcPcs_f, &value, &cs_en, hscs_idx, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcCsCtlEnClk_enClkMcHata_f, &value, &cs_en, hscs_idx, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cs_en));
    }

    /*CtcFlexeCrossCtlEnClk*/
    for(dp = 0; dp < SYS_TMM_DP_NUM; dp++)
    {
        SYS_CONDITION_CONTINUE(FALSE == flexe_down_flag[dp]);

        index = DRV_INS(dp, 0);

        tbl_id = CtcFlexeCrossCtlEnClk_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fc_en));
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeCrossCtlEnClk_enClkMcu_f, &value, &fc_en, dp, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeCrossCtlEnClk_enClkMcuIntf_f, &value, &fc_en, dp, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeCrossCtlEnClk_enClkFlexeCross_f, &value, &fc_en, dp, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeCrossCtlEnClk_enClkFlexeCrossReg_f, &value, &fc_en, dp, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fc_en));
    }

    /*CtcFlexeShimCtlEnClk*/
    for(dp = 0; dp < SYS_TMM_DP_NUM; dp++)
    {
        SYS_CONDITION_CONTINUE(FALSE == flexe_down_flag[dp]);

        index = DRV_INS(dp, 0);

        tbl_id = CtcFlexeShimCtlEnClk_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fs_en));
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeShimCtlEnClk_enClkFlexeShim_f, &value, &fs_en, dp, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeShimCtlEnClk_enClkFlexeShimReg_f, &value, &fs_en, dp, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeShimCtlEnClk_enClkFlexeMgr_f, &value, &fs_en, dp, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fs_en));
    }

    if((DRV_CHIP_SUB_TYPE_1 == DRV_CHIP_SUB_TYPE(lchip)) || (DRV_CHIP_SUB_TYPE_2 == DRV_CHIP_SUB_TYPE(lchip)))
    {
        for(dp = 0; dp < SYS_TMM_DP_NUM; dp++)
        {
            index = DRV_INS(dp, 0);

            tbl_id = CtcFlexeCrossCtlEnClk_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fc_en));
            DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeCrossCtlEnClk_enClkFlexeCross_f, &value, &fc_en, dp, 0);
            DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeCrossCtlEnClk_enClkFlexeCrossReg_f, &value, &fc_en, dp, 0);
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fc_en));

            tbl_id = CtcFlexeShimCtlEnClk_t;
            cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fs_en));
            DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeShimCtlEnClk_enClkFlexeShim_f, &value, &fs_en, dp, 0);
            DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeShimCtlEnClk_enClkFlexeShimReg_f, &value, &fs_en, dp, 0);
            DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcFlexeShimCtlEnClk_enClkFlexeMgr_f, &value, &fs_en, dp, 0);
            cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &fs_en));
        }
    }

    /*CtcDpTxCtlClockEn*/
    /*for(dp = 0; dp < SYS_TMM_DP_NUM; dp++)
    {
        SYS_CONDITION_CONTINUE(FALSE == dp_down_flag[dp]);

        index = DRV_INS(dp, 0);

        tbl_id = CtcDpTxCtlClockEn_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &dp_tx_en));
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcDpTxCtlClockEn_enClkCtcDpTx_f, &value, &dp_tx_en, dp, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcDpTxCtlClockEn_enClkMacSecEnc_f, &value, &dp_tx_en, dp, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &dp_tx_en));
    }*/

    /*CtcDpRxCtlClockEn*/
    /*for(dp = 0; dp < SYS_TMM_DP_NUM; dp++)
    {
        SYS_CONDITION_CONTINUE(FALSE == dp_down_flag[dp]);

        index = DRV_INS(dp, 0);

        tbl_id = CtcDpRxCtlClockEn_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &dp_rx_en));
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcDpRxCtlClockEn_enClkCtcDpRx_f, &value, &dp_rx_en, dp, 0);
        DRV_IOW_FIELD_NZ(lchip, tbl_id, CtcDpRxCtlClockEn_enClkMacSecDec_f, &value, &dp_rx_en, dp, 0);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &dp_rx_en));
    }*/

    /*CpuMacCtlEnClk*/
    if(cm_down_flag)
    {
        index = 0;

        tbl_id = CpuMacCtlEnClk_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm_en));
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkLed_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkQuadSgmac_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkSgmac0_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkSgmac1_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkSgmac2_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkSgmac3_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkSgmiiPcs0_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkSgmiiPcs1_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkSgmiiPcs2_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkSgmiiPcs3_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkXfiPcs0_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkXfiPcs1_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkXfiPcs2_f, &value, &cm_en);
        DRV_IOW_FIELD(lchip, tbl_id, CpuMacCtlEnClk_enClkXfiPcs3_f, &value, &cm_en);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cm_en));
    }

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_pulse_init(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 value = 0;
    RefDivCpuMacPulse_m  rd_cpumac;
    RefDivMcPcsLinkPulse_m rd_pcs;
    RefDivMcMacPulse_m   rd_mac;
    RefDivCoppUpdPulse_m rd_copp;
    RefDivDlbPulse_m     rd_dlb;
    RefDivEfdPulse_m     rd_efd;
    RefDivLagEnginePulse_m rd_lag;
    RefDivNetTxEeePulse_m rd_nettx;
    RefDivPolicingUpdPulse_m rd_plc;
    RefDivQMgrDeqShpPulse_m rd_qmgr;
    RefDivSpnOamTxPulse_m rd_spn;
    RefDivStormCtlUpdPulse_m rd_sto;

    /*RefDiv reset*/
    cmd = DRV_IOR(RefDivCpuMacPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_cpumac));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivCpuMacPulse_t, RefDivCpuMacPulse_cfgResetDivCpuMacLinkFilterPulse_f,  &value, &rd_cpumac);
    DRV_IOW_FIELD(lchip, RefDivCpuMacPulse_t, RefDivCpuMacPulse_cfgResetDivCpuMacLinkPulse_f,        &value, &rd_cpumac);
    DRV_IOW_FIELD(lchip, RefDivCpuMacPulse_t, RefDivCpuMacPulse_cfgResetDivCpuMacPauseLockPulse_f,   &value, &rd_cpumac);
    DRV_IOW_FIELD(lchip, RefDivCpuMacPulse_t, RefDivCpuMacPulse_cfgResetDivCpuMacPauseTimer0Pulse_f, &value, &rd_cpumac);
    DRV_IOW_FIELD(lchip, RefDivCpuMacPulse_t, RefDivCpuMacPulse_cfgResetDivCpuMacPauseTimer1Pulse_f, &value, &rd_cpumac);
    DRV_IOW_FIELD(lchip, RefDivCpuMacPulse_t, RefDivCpuMacPulse_cfgResetDivCpuMacPauseTimer2Pulse_f, &value, &rd_cpumac);
    DRV_IOW_FIELD(lchip, RefDivCpuMacPulse_t, RefDivCpuMacPulse_cfgResetDivCpuMacPauseTimer3Pulse_f, &value, &rd_cpumac);
    cmd = DRV_IOW(RefDivCpuMacPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_cpumac));

    cmd = DRV_IOR(RefDivMcPcsLinkPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_pcs));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivMcPcsLinkPulse_t, RefDivMcPcsLinkPulse_cfgResetDivMcMac0Dp0McPcsLinkPulse_f, &value, &rd_pcs);
    DRV_IOW_FIELD(lchip, RefDivMcPcsLinkPulse_t, RefDivMcPcsLinkPulse_cfgResetDivMcMac0Dp1McPcsLinkPulse_f, &value, &rd_pcs);
    DRV_IOW_FIELD(lchip, RefDivMcPcsLinkPulse_t, RefDivMcPcsLinkPulse_cfgResetDivMcMac1Dp0McPcsLinkPulse_f, &value, &rd_pcs);
    DRV_IOW_FIELD(lchip, RefDivMcPcsLinkPulse_t, RefDivMcPcsLinkPulse_cfgResetDivMcMac1Dp1McPcsLinkPulse_f, &value, &rd_pcs);
    DRV_IOW_FIELD(lchip, RefDivMcPcsLinkPulse_t, RefDivMcPcsLinkPulse_cfgResetDivMcMac2Dp0McPcsLinkPulse_f, &value, &rd_pcs);
    DRV_IOW_FIELD(lchip, RefDivMcPcsLinkPulse_t, RefDivMcPcsLinkPulse_cfgResetDivMcMac2Dp1McPcsLinkPulse_f, &value, &rd_pcs);
    DRV_IOW_FIELD(lchip, RefDivMcPcsLinkPulse_t, RefDivMcPcsLinkPulse_cfgResetDivMcMac3Dp0McPcsLinkPulse_f, &value, &rd_pcs);
    DRV_IOW_FIELD(lchip, RefDivMcPcsLinkPulse_t, RefDivMcPcsLinkPulse_cfgResetDivMcMac3Dp1McPcsLinkPulse_f, &value, &rd_pcs);
    cmd = DRV_IOW(RefDivMcPcsLinkPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_pcs));

    cmd = DRV_IOR(RefDivMcMacPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_mac));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp0LinkFilterPulse_f,       &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp0SgmacPauseLockPulse_f,   &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp0SgmacPauseTimer0Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp0SgmacPauseTimer1Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp0SgmacPauseTimer2Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp0SgmacPauseTimer3Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp1LinkFilterPulse_f,       &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp1SgmacPauseLockPulse_f,   &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp1SgmacPauseTimer0Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp1SgmacPauseTimer1Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp1SgmacPauseTimer2Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac0Dp1SgmacPauseTimer3Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp0LinkFilterPulse_f,       &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp0SgmacPauseLockPulse_f,   &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp0SgmacPauseTimer0Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp0SgmacPauseTimer1Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp0SgmacPauseTimer2Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp0SgmacPauseTimer3Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp1LinkFilterPulse_f,       &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp1SgmacPauseLockPulse_f,   &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp1SgmacPauseTimer0Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp1SgmacPauseTimer1Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp1SgmacPauseTimer2Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac1Dp1SgmacPauseTimer3Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp0LinkFilterPulse_f,       &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp0SgmacPauseLockPulse_f,   &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp0SgmacPauseTimer0Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp0SgmacPauseTimer1Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp0SgmacPauseTimer2Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp0SgmacPauseTimer3Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp1LinkFilterPulse_f,       &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp1SgmacPauseLockPulse_f,   &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp1SgmacPauseTimer0Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp1SgmacPauseTimer1Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp1SgmacPauseTimer2Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac2Dp1SgmacPauseTimer3Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp0LinkFilterPulse_f,       &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp0SgmacPauseLockPulse_f,   &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp0SgmacPauseTimer0Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp0SgmacPauseTimer1Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp0SgmacPauseTimer2Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp0SgmacPauseTimer3Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp1LinkFilterPulse_f,       &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp1SgmacPauseLockPulse_f,   &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp1SgmacPauseTimer0Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp1SgmacPauseTimer1Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp1SgmacPauseTimer2Pulse_f, &value, &rd_mac);
    DRV_IOW_FIELD(lchip, RefDivMcMacPulse_t, RefDivMcMacPulse_cfgResetDivMcMac3Dp1SgmacPauseTimer3Pulse_f, &value, &rd_mac);
    cmd = DRV_IOW(RefDivMcMacPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_mac));

    cmd = DRV_IOR(RefDivCoppUpdPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_copp));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivCoppUpdPulse_t, RefDivCoppUpdPulse_cfgResetDivCoppEpeUpdPulse_f,  &value, &rd_copp);
    DRV_IOW_FIELD(lchip, RefDivCoppUpdPulse_t, RefDivCoppUpdPulse_cfgResetDivCoppIpeUpdPulse_f,  &value, &rd_copp);
    cmd = DRV_IOW(RefDivCoppUpdPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_copp));

    cmd = DRV_IOR(RefDivDlbPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_dlb));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivDlbPulse_t, RefDivDlbPulse_cfgResetDivDlbPulse_f,  &value, &rd_dlb);
    cmd = DRV_IOW(RefDivDlbPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_dlb));

    cmd = DRV_IOR(RefDivEfdPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_efd));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivEfdPulse_t, RefDivEfdPulse_cfgResetDivEfdPulse_f,  &value, &rd_efd);
    cmd = DRV_IOW(RefDivEfdPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_efd));

    cmd = DRV_IOR(RefDivLagEnginePulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_lag));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivLagEnginePulse_t, RefDivLagEnginePulse_cfgResetDivLagEngineChanAvgLoadPulse_f,         &value, &rd_lag);
    DRV_IOW_FIELD(lchip, RefDivLagEnginePulse_t, RefDivLagEnginePulse_cfgResetDivLagEngineChanAvgQSizePulse_f,        &value, &rd_lag);
    DRV_IOW_FIELD(lchip, RefDivLagEnginePulse_t, RefDivLagEnginePulse_cfgResetDivLagEngineFlowSetActiveUpdatePulse_f, &value, &rd_lag);
    cmd = DRV_IOW(RefDivLagEnginePulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_lag));

    cmd = DRV_IOR(RefDivNetTxEeePulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_nettx));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivNetTxEeePulse_t, RefDivNetTxEeePulse_cfgResetDivSlice0Dp0NetTxEeePulse_f,  &value, &rd_nettx);
    DRV_IOW_FIELD(lchip, RefDivNetTxEeePulse_t, RefDivNetTxEeePulse_cfgResetDivSlice0Dp1NetTxEeePulse_f,  &value, &rd_nettx);
    cmd = DRV_IOW(RefDivNetTxEeePulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_nettx));

    cmd = DRV_IOR(RefDivPolicingUpdPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_plc));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivPolicingUpdPulse_t, RefDivPolicingUpdPulse_cfgResetDivEpePolicing0UpdPulse_f, &value, &rd_plc);
    DRV_IOW_FIELD(lchip, RefDivPolicingUpdPulse_t, RefDivPolicingUpdPulse_cfgResetDivEpePolicing1UpdPulse_f, &value, &rd_plc);
    DRV_IOW_FIELD(lchip, RefDivPolicingUpdPulse_t, RefDivPolicingUpdPulse_cfgResetDivIpePolicing0UpdPulse_f, &value, &rd_plc);
    DRV_IOW_FIELD(lchip, RefDivPolicingUpdPulse_t, RefDivPolicingUpdPulse_cfgResetDivIpePolicing1UpdPulse_f, &value, &rd_plc);
    DRV_IOW_FIELD(lchip, RefDivPolicingUpdPulse_t, RefDivPolicingUpdPulse_cfgResetDivSvcPolicingUpdPulse_f,  &value, &rd_plc);
    cmd = DRV_IOW(RefDivPolicingUpdPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_plc));

    cmd = DRV_IOR(RefDivQMgrDeqShpPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_qmgr));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivQMgrDeqShpPulse_t, RefDivQMgrDeqShpPulse_cfgResetDivQMgrDeqShpPulse_f,  &value, &rd_qmgr);
    cmd = DRV_IOW(RefDivQMgrDeqShpPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_qmgr));

    cmd = DRV_IOR(RefDivSpnOamTxPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_spn));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivSpnOamTxPulse_t, RefDivSpnOamTxPulse_cfgResetDivSpnOamTxPulse_f,  &value, &rd_spn);
    cmd = DRV_IOW(RefDivSpnOamTxPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_spn));

    cmd = DRV_IOR(RefDivStormCtlUpdPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_sto));
    value = 0;
    DRV_IOW_FIELD(lchip, RefDivStormCtlUpdPulse_t, RefDivStormCtlUpdPulse_cfgResetDivStormCtl0UpdPulse_f,  &value, &rd_sto);
    DRV_IOW_FIELD(lchip, RefDivStormCtlUpdPulse_t, RefDivStormCtlUpdPulse_cfgResetDivStormCtl1UpdPulse_f,  &value, &rd_sto);
    cmd = DRV_IOW(RefDivStormCtlUpdPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &rd_sto));

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_init(uint8 lchip, ctc_datapath_global_cfg_t* p_datapath_cfg)
{
    if(g_dmps_dbg_sw)
    {
        if(NULL == g_tm_dump_fp)
        {
            g_tm_dump_fp = sal_fopen("./dump.txt", "w+");
        }
        if(NULL == g_tmm_serdes_init_dump_fp)
        {
            g_tmm_serdes_init_dump_fp = sal_fopen("./serdes_init_dump.txt", "w+");
        }
    }

    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n#########################\n");
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "#    1, sys_tmm_datapath_init start #\n");
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "#########################\n");

    /*1. datapath_cfg.txt param check*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_cfg_param_check(lchip, p_datapath_cfg));

    #if (SDB_MEM_MODEL != SDB_MODE)
    /*2. do core clock init */
    CTC_ERROR_RETURN(_sys_tmm_datapath_core_clock_init(lchip, p_datapath_cfg->core_frequency_a));
    
    /*3. do sup init*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_sup_init(lchip));

    /*4. do packet buffer init*/
    if ((DRV_CHIP_SUB_TYPE_4 == DRV_CHIP_SUB_TYPE(lchip)) && DRV_IS_TMM(lchip))
    {
        CTC_ERROR_RETURN(_sys_tmm_datapath_packet_buffer_init(lchip));
    }
    #endif
    /*5. prepare data base*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_init_db(lchip, p_datapath_cfg));

    #if (SDB_MEM_MODEL != SDB_MODE)
    /*6. module init*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_module_init(lchip));
    
    /*7. do serdes init */
    //if(!sys_usw_chip_get_reset_hw_en(lchip))
    {
        CTC_ERROR_RETURN(sys_tmm_datapath_init_serdes(lchip, p_datapath_cfg));
    }
    /*8. dp/hss/txqm power down*/
    CTC_ERROR_RETURN(sys_tmm_datapath_init_macpcs_power_down(lchip, p_datapath_cfg));

    /*9. do omitted table init*/
    CTC_ERROR_RETURN(_sys_tmm_datapath_omitted_table_init(lchip));
    #endif
            

#ifdef EMULATION_ENV
        uint8 board_type = 0;
        TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n #### Now source Cmodel datapath config.....\n\n\n");
        switch (p_datapath_cfg->serdes[0].mode)
        {
        case CTC_CHIP_SERDES_XXVG_MODE:
            board_type = 0;
            break;
        case CTC_CHIP_SERDES_LG_MODE:
            board_type = 1;
            break;
        case CTC_CHIP_SERDES_LG_R1_MODE:
            board_type = 2;
            break;
        case CTC_CHIP_SERDES_CG_R2_MODE:
            board_type = 3;
            break;
        case CTC_CHIP_SERDES_CG_MODE:
            board_type = 4;
            break;
        case CTC_CHIP_SERDES_XLG_MODE:
            board_type = 5;
            break;
        case CTC_CHIP_SERDES_XFI_MODE:
            board_type = 6;
            break;
        case CTC_CHIP_SERDES_CCG_R4_MODE:
            board_type = 7;
            break;
        case CTC_CHIP_SERDES_CDG_R8_MODE:
            board_type = 8;
            break;
        default:
            board_type = 0;
            break;
        }
        CTC_ERROR_RETURN(_sys_tmm_cmodel_datapath_init(board_type, 0xff));
#endif

    #if (SDB_MEM_MODEL != SDB_MODE)
    /*10. do datapath init */
    CTC_ERROR_RETURN(_sys_tmm_datapath_dp_init(lchip, p_datapath_cfg));

    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "\n#########################\n");
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "#   1, sys_tmm_datapath_init end  #\n");
    TSINGMA_DUMP_PRINT(g_tm_dump_fp, "#########################\n");

    /*11. pulse init*/
    CTC_ERROR_RETURN(sys_tmm_datapath_pulse_init(lchip));

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DATAPATH, SYS_WB_APPID_DATAPATH_SUBID_MASTER, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_DATAPATH, SYS_WB_APPID_DATAPATH_SUBID_HSS_ATTRIBUTE, 1);

    CTC_ERROR_RETURN(_sys_tmm_datapath_set_ipe_popslot(lchip, TRUE, NULL));

    #endif 
    
    return CTC_E_NONE;
}

int32
_sys_tmm_serdes_set_mode(uint8 lchip, ctc_chip_serdes_info_t* p_serdes_info, uint16 overclocking_speed, sys_tmm_ds_target_attr_t *target)
{
    uint8  remap_flag = FALSE;
    uint8  logical_serdes_id;
    uint8  dup_flag   = FALSE;
    sys_datapath_serdes_info_t* p_serdes = NULL;

    CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, 
        p_serdes_info->serdes_id, &logical_serdes_id));
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);

    /*HS PAM4 remap flag*/
    remap_flag = sys_tmm_dynamic_switch_judge_remap(lchip, logical_serdes_id, p_serdes_info->serdes_mode);
    if(remap_flag)
    {
        CTC_ERROR_RETURN(sys_tmm_dynamic_switch_para_check(lchip, logical_serdes_id, 
            p_serdes_info->serdes_mode, overclocking_speed, &dup_flag, remap_flag));
        SYS_CONDITION_RETURN(dup_flag, CTC_E_NONE);
        CTC_ERROR_RETURN(sys_tmm_mac_dynamic_switch_remap_proc(lchip, p_serdes_info->serdes_mode, 
            logical_serdes_id, overclocking_speed));
        return CTC_E_NONE;
    }

    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));

    CTC_ERROR_RETURN(sys_tmm_dynamic_switch_para_check(lchip, logical_serdes_id, 
        p_serdes_info->serdes_mode, overclocking_speed, &dup_flag, remap_flag));
    SYS_CONDITION_RETURN(dup_flag, CTC_E_NONE);

    CTC_ERROR_RETURN(_sys_tmm_datapath_dynamic_switch_get_info(lchip, logical_serdes_id, 
        p_serdes->mode, p_serdes_info->serdes_mode, target, overclocking_speed));

    CTC_ERROR_RETURN(_sys_tmm_mac_set_interface_mode(lchip, p_serdes_info->serdes_mode, target));
    
    return CTC_E_NONE;
}

int32 _sys_tmm_serdes_set_mode_ovclk_chk(uint8 serdes_id, uint8 serdes_mode, uint8 overclocking_speed)
{
    /* Normal NetWork Port
     * XFI & XLG support overclocking-speed:
     *    CTC_CHIP_SERDES_OCS_MODE_NONE = 0
     *    CTC_CHIP_SERDES_OCS_MODE_11_06G = 1, 
     *    CTC_CHIP_SERDES_OCS_MODE_12_12G = 2, 
     *    CTC_CHIP_SERDES_OCS_MODE_12_58G = 3, 
     *    CTC_CHIP_SERDES_OCS_MODE_10_6G = 5,  
     *    CTC_CHIP_SERDES_OCS_MODE_11_06G11 = 11,
     *    CTC_CHIP_SERDES_OCS_MODE_12_58G12 = 12,
     * XXVG & LG & CG support overclocking-speed:
     *    CTC_CHIP_SERDES_OCS_MODE_NONE = 0,
     *    CTC_CHIP_SERDES_OCS_MODE_27_27G = 4, 
     *    CTC_CHIP_SERDES_OCS_MODE_26_52G = 7, 
     *    CTC_CHIP_SERDES_OCS_MODE_26_9G = 8,  
     * PAM4 support overclocking-speed:
     *    CTC_CHIP_SERDES_OCS_MODE_NONE = 0, 
     *    CTC_CHIP_SERDES_OCS_MODE_52_71G = 14, 
     * Other support overclocking-speed:
     *    CTC_CHIP_SERDES_OCS_MODE_NONE = 0
     *
     * CPUMAC NetWork Prot
     * XFI & XLG support overclocking-speed:
     *    CTC_CHIP_SERDES_OCS_MODE_NONE = 0
     *    CTC_CHIP_SERDES_OCS_MODE_11_06G = 1, 
     *    CTC_CHIP_SERDES_OCS_MODE_12_12G = 2, 
     *    CTC_CHIP_SERDES_OCS_MODE_12_58G = 3, 
     *    CTC_CHIP_SERDES_OCS_MODE_11_06G11 = 11,
     *    CTC_CHIP_SERDES_OCS_MODE_12_58G12 = 12,
     * XXVG & LG & CG support overclocking-speed:
     *    CTC_CHIP_SERDES_OCS_MODE_NONE = 0,
     *    CTC_CHIP_SERDES_OCS_MODE_27_27G = 4, 
     */
    uint8 chk_flag = 0;
    uint16 xfi_xlg_bitmap = 0x182f; //0b0001 1000 0010 1111 ,  ctc_chip_serdes_ocs_mode_t
    uint16 xxvg_lg_cg_bitmap = 0x0191; //0b0000 0001 1001 0001 ,  ctc_chip_serdes_ocs_mode_t
    uint16 pam4_bitmap = 0x4001; //0b0100 0001 1001 0001 ,  ctc_chip_serdes_ocs_mode_t
    uint16 xfi_xlg_bitmap_cpumac = 0x180f; //0b0001 1000 0000 1111 ,  ctc_chip_serdes_ocs_mode_t
    uint16 xxvg_lg_cg_bitmap_cpumac = 0x0011; //0b0000 0000 0001 0001 ,  ctc_chip_serdes_ocs_mode_t
    
    if((CTC_CHIP_SERDES_XFI_MODE == serdes_mode) || (CTC_CHIP_SERDES_XLG_MODE == serdes_mode))
    {
        /*CPUMAC*/
        if(SYS_TMM_CPUMAC_SERDES_START_ID <= serdes_id)
        {
            chk_flag = (xfi_xlg_bitmap_cpumac >> overclocking_speed) & 0x1;
        }
        else
        {
            chk_flag = (xfi_xlg_bitmap >> overclocking_speed) & 0x1;
        }
    }
    else if((CTC_CHIP_SERDES_XXVG_MODE == serdes_mode) || \
                    (CTC_CHIP_SERDES_LG_MODE == serdes_mode) || \
                           (CTC_CHIP_SERDES_CG_MODE == serdes_mode))
    {
        /*CPUMAC*/
        if(SYS_TMM_CPUMAC_SERDES_START_ID <= serdes_id)
        {
            chk_flag = (xxvg_lg_cg_bitmap_cpumac >> overclocking_speed) & 0x1;
        }
        else
        {
            chk_flag = (xxvg_lg_cg_bitmap >> overclocking_speed) & 0x1;
        }
    }
    else if((CTC_CHIP_SERDES_LG_R1_MODE == serdes_mode) || \
                    (CTC_CHIP_SERDES_CG_R2_MODE == serdes_mode) || \
                           (CTC_CHIP_SERDES_CCG_R4_MODE == serdes_mode) || \
                             (CTC_CHIP_SERDES_CDG_R8_MODE == serdes_mode))
    {
        chk_flag = (pam4_bitmap >> overclocking_speed) & 0x1;
    }
    else
    {
        chk_flag = (CTC_CHIP_SERDES_OCS_MODE_NONE == overclocking_speed ? 1 : 0);
    }

    if(1 != chk_flag)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Unsupported dst overclocking-speed.\n");
        return CTC_E_NOT_SUPPORT;
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_cpumac_serdes_set_ovclk_speed(uint8 lchip, ctc_chip_serdes_info_t* p_serdes_info, uint8 src_mode, uint8 src_ovclk_speed)
{
    uint8 index = 0;
    uint8 logical_serdes_id = 0;
    uint8 first_physical_serdes_id = 0;
    uint8 physical_serdes_id;
    uint8 serdes_num = 1;
    uint16 ovclk_flag = 0;

    if(src_mode != p_serdes_info->serdes_mode)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% SerDes    96 to 99 Only Support Overclocking-Speed Configure. Src Mode must equal Dst Mode.\n");
        return CTC_E_INVALID_PARAM;
    }
    else
    {
        if(src_ovclk_speed != p_serdes_info->overclocking_speed)
        {
            /*overclk speed configure*/
            ovclk_flag = p_serdes_info->overclocking_speed;
            
            switch(src_mode)
            {
                case CTC_CHIP_SERDES_XFI_MODE:
                case CTC_CHIP_SERDES_XXVG_MODE:
                    serdes_num = 1;
                    break;
                case CTC_CHIP_SERDES_LG_MODE:
                    serdes_num = 2;
                    break;
                case CTC_CHIP_SERDES_XLG_MODE:
                case CTC_CHIP_SERDES_CG_MODE:
                    serdes_num = 4;
                    break;
                default:
                    return CTC_E_INVALID_PARAM;
            }
        }
        else
        {
            return CTC_E_NONE;
        }
    }

    physical_serdes_id = p_serdes_info->serdes_id;
    first_physical_serdes_id = physical_serdes_id - (physical_serdes_id % serdes_num);

    for(index = 0; index < serdes_num; index ++)
    {

        physical_serdes_id = first_physical_serdes_id + index;
        logical_serdes_id = physical_serdes_id;
        CTC_ERROR_RETURN(_sys_tmm_dynamic_switch_serdes_cfg(lchip, physical_serdes_id, logical_serdes_id, src_mode, \
                                                                                   p_serdes_info->serdes_mode, ovclk_flag));
    }

    return CTC_E_NONE;
}

int32
_sys_tmm_serdes_set_mode_proc(uint8 lchip, ctc_chip_serdes_info_t* p_serdes_info)
{
    uint8  physical_serdes_id;
    uint16 overclocking_speed;
    uint8  logical_serdes_id                = 0;
    uint8  first_logical_serdes_id          = 0;
    uint8  dst_serdes_num                   = 1;
    uint8  pam4_or_nrz                      = 0;
    uint16 lport                            = 0;
    uint32 is_bind_flexe_group              = 0;
    sys_datapath_lport_attr_t*  port_attr   = NULL;
    sys_datapath_serdes_info_t* p_serdes    = NULL;
    sys_tmm_ds_target_attr_t    target      = {0};
    ctc_chip_serdes_info_t      serdes_info = {0};

    sal_memcpy(&serdes_info, p_serdes_info, sizeof(ctc_chip_serdes_info_t));

    physical_serdes_id = (uint8) serdes_info.serdes_id;
    overclocking_speed = serdes_info.overclocking_speed;

    /*check parameter*/
    CTC_ERROR_RETURN(_sys_tmm_serdes_set_mode_ovclk_chk(physical_serdes_id, serdes_info.serdes_mode, overclocking_speed));

    if(CTC_CHIP_SERDES_XLG_R2_MODE == serdes_info.serdes_mode)
    {
        serdes_info.serdes_mode = CTC_CHIP_SERDES_LG_MODE;
        overclocking_speed = CTC_CHIP_SERDES_OCS_MODE_20_625G;
    }

    CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, physical_serdes_id, &logical_serdes_id));
    if(SYS_TMM_USELESS_ID8 == logical_serdes_id)
    {
        return CTC_E_INVALID_PARAM;
    }

    /*HS PAM4 check: for dst mode CGR2, change logic serdes to 0; for dst mode LGR1, lane 1 & 3 is not allowed*/
    if(((31 >= logical_serdes_id) || ((48 <= logical_serdes_id) && (79 >= logical_serdes_id))) && 
       (0 != logical_serdes_id % 2) && 
       SYS_TMM_MODE_IS_PAM4(serdes_info.serdes_mode))
    {
        if(CTC_CHIP_SERDES_CG_R2_MODE == serdes_info.serdes_mode)
        {
            logical_serdes_id = logical_serdes_id / 4 * 4;
            CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, logical_serdes_id, 
                ((uint8*) &(serdes_info.serdes_id))));
        }
        else
        {
            SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Logic SerDes %u do not support PAM4!\n", logical_serdes_id);
            return CTC_E_NOT_SUPPORT;
        }
    }

    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logical_serdes_id, &p_serdes));
    if(NULL == p_serdes)
    {
        return CTC_E_INVALID_PTR;
    }

    /*NONE--> NONE*/
    if((CTC_CHIP_SERDES_NONE_MODE == serdes_info.serdes_mode) && (CTC_CHIP_SERDES_NONE_MODE == p_serdes->mode))
    {
        return CTC_E_NONE;
    }

    if(CTC_E_NONE == sys_tmm_get_lport_chan_map_by_logic_serdes(lchip, logical_serdes_id, NULL, &lport))
    {
        port_attr = sys_usw_datapath_get_port_capability(lchip, lport);
        if(NULL == port_attr)
        {
            return CTC_E_INVALID_PTR;
        }

        /* check src port whether bind in group */
        CTC_ERROR_RETURN(sys_tmm_flexe_check_serdes_bind_group(lchip, port_attr->multi_serdes_id[0], &is_bind_flexe_group));
        if (is_bind_flexe_group)
        {
            SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% SerDes %d is bind to flexe group, cannot run dynamic switch ! \n", port_attr->multi_serdes_id[0]);
            return CTC_E_PARAM_CONFLICT;
        }
    }

    CTC_ERROR_RETURN(sys_tmm_serdes_get_glb_info(lchip, physical_serdes_id, SYS_TMM_SERDES_GLB_MD_MODE, &pam4_or_nrz));

    /*find 1st lane for switch*/
    SYS_TMM_GET_LANE_NUM_BY_MODE(serdes_info.serdes_mode, dst_serdes_num);

    first_logical_serdes_id = logical_serdes_id - ( logical_serdes_id % dst_serdes_num);

    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, first_logical_serdes_id, &p_serdes));

    CTC_ERROR_RETURN(_sys_usw_datapath_get_physical_serdes_id_by_logical(lchip, first_logical_serdes_id, ((uint8*) &(serdes_info.serdes_id))));

    if((overclocking_speed == p_serdes->overclocking_speed) && (serdes_info.serdes_mode == p_serdes->mode))
    {
        return CTC_E_NONE;
    }
    else
    {
        CTC_ERROR_RETURN(_sys_tmm_serdes_set_mode(lchip, &serdes_info, overclocking_speed, &target));
    }

    return CTC_E_NONE;
}

int32
sys_tmm_serdes_set_mode(uint8 lchip, ctc_chip_serdes_info_t* p_serdes_info)
{
    MAC_LOCK;
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_tmm_serdes_set_mode_proc(lchip, p_serdes_info));
    MAC_UNLOCK;

    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_serdes_check_by_physical_serdes_id(uint8 lchip, uint8 physical_serdes_id)
{
    uint8 hss_idx       = 0;
    uint8 logic_serdes_id = 0;
    sys_datapath_hss_attribute_t* p_hss_vec = NULL;

    CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, physical_serdes_id, &logic_serdes_id));
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logic_serdes_id), CTC_E_INVALID_PARAM);

    hss_idx = SYS_TMM_MAP_SERDES_TO_HSS_IDX(logic_serdes_id);

    p_hss_vec = ctc_vector_get(p_usw_datapath_master[lchip]->p_hss_vector, hss_idx);
    
    if (p_hss_vec == NULL)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Feature not initialized \n");
        return CTC_E_NOT_INIT;

    }
    
    return CTC_E_NONE;
}

int32
sys_tmm_datapath_set_serdes_prbs(uint8 lchip, void* p_data)
{
    uint16 lport    = 0;
    uint8 logic_serdes_id = 0;
    ctc_chip_serdes_prbs_t* p_prbs = (ctc_chip_serdes_prbs_t*)p_data;
    CTC_PTR_VALID_CHECK(p_prbs);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, value:%d, type:%d, mode:%d\n", p_prbs->serdes_id, p_prbs->value, p_prbs->polynome_type, p_prbs->mode);

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, p_prbs->serdes_id));

    CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, p_prbs->serdes_id, &logic_serdes_id));
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logic_serdes_id), CTC_E_INVALID_PARAM);

    CTC_ERROR_RETURN(sys_tmm_get_lport_chan_map_by_logic_serdes(lchip, logic_serdes_id, NULL, &lport));

    switch(p_prbs->mode)
    {
        case 0: /* 0--Rx */
            CTC_ERROR_RETURN(sys_tmm_serdes_set_rx_prbs_check(lchip, p_prbs));
            break;
        case 1: /* 1--Tx */
            CTC_ERROR_RETURN(sys_tmm_serdes_set_tx_prbs(lchip, p_prbs));
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_serdes_prbs(uint8 lchip, void* p_data)
{
    uint32 cmd = 0;
    uint32 field_val = 0;
    ctc_chip_serdes_prbs_t* p_prbs = (ctc_chip_serdes_prbs_t*)p_data;
    CTC_PTR_VALID_CHECK(p_prbs);
    
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, mode:%d\n", p_prbs->serdes_id, p_prbs->mode);

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, p_prbs->serdes_id));

    switch(p_prbs->mode)
    {
        case 0: /* 0--Rx */
            cmd = DRV_IOR(OobFcReserved_t, OobFcReserved_reserved_f);
            DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val);
            if (1 == field_val)
            {
                SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "get prbs rx information, must close link monitor thread\n");
                return CTC_E_INVALID_CONFIG;
            }
            CTC_ERROR_RETURN(sys_tmm_serdes_get_rx_prbs_check(lchip, p_prbs));
            break;
        case 1: /* 1--Tx */
            CTC_ERROR_RETURN(sys_tmm_serdes_get_tx_prbs(lchip, p_prbs));
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

/*
set serdes polarity (hard & soft tables, init & set)
*/
int32
sys_tmm_datapath_set_serdes_polarity(uint8 lchip, void* p_data)
{
    uint8  serdes_id = 0;
    ctc_chip_serdes_polarity_t*   p_polarity = (ctc_chip_serdes_polarity_t*)p_data;

    DATAPATH_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_polarity);
    serdes_id = p_polarity->serdes_id;

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, serdes_id));

    CTC_ERROR_RETURN(sys_tmm_serdes_set_polarity(lchip, serdes_id, p_polarity->dir, p_polarity->polarity_mode));

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_serdes_polarity(uint8 lchip, void* p_data)
{
    uint8  physical_serdes_id = 0;
    uint8  value     = 0;
    ctc_chip_serdes_polarity_t*   p_polarity = (ctc_chip_serdes_polarity_t*)p_data;

    DATAPATH_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_polarity);
    
    physical_serdes_id = p_polarity->serdes_id;

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, physical_serdes_id));

    CTC_ERROR_RETURN(sys_tmm_serdes_get_polarity(lchip, physical_serdes_id, p_polarity->dir, &value));

    p_polarity->polarity_mode = value;

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_ffe_typical_value(uint8 lchip, ctc_chip_serdes_ffe_t* p_ffe)
{
    uint8 serdes_mode = 0;
    uint8 pam4_or_nrz = 0;
    uint8 coeff_index = 0;
    int16 *p_coeff = NULL;
    
    int16 coefficient_int16_nrz[][CTC_CHIP_FFE_PARAM_NUM] = {
        {0, 0, 36, -6, -2},   /*0-3 inch, M6G, 25G/50G/100G optical module*/
        {0, 0, 40, -8, -2},   /*3-6 inch, M6G, 25G/50G/100G optical module*/
        {0, 0, 44, -12, -2},  /*6-9 inch, M6G, 25G/50G/100G optical module*/
    };

    CTC_ERROR_RETURN(sys_tmm_serdes_get_glb_info(lchip, p_ffe->serdes_id, SYS_TMM_SERDES_GLB_MD_MODE, &pam4_or_nrz));
    CTC_ERROR_RETURN(sys_tmm_serdes_get_glb_info(lchip, p_ffe->serdes_id, SYS_TMM_SERDES_GLB_DATA_RATE, &serdes_mode));

    if(SYS_TMM_SERDES_PAM4_MODE == pam4_or_nrz)
    {
        return CTC_E_NOT_SUPPORT;
    }

    /*2--M6*/
    if(2 == p_ffe->board_material)
    {
        if((CTC_CHIP_SERDES_XXVG_MODE == serdes_mode) || 
              (CTC_CHIP_SERDES_LG_MODE == serdes_mode) ||
                 (CTC_CHIP_SERDES_CG_MODE == serdes_mode))
        {
            if(0 == p_ffe->trace_len) /*0 - 3 inch*/
            {
                coeff_index = 0;
            }
            else if(1 == p_ffe->trace_len) /*3 - 6 inch*/
            {
                coeff_index = 1;
            }
            else /*6 - 9 inch*/
            {
                coeff_index = 2;
            }
        }
        else
        {
            coeff_index = 0xff;
        }
    }
    /*1--M4*/
    else if(1 == p_ffe->board_material)
    {
        coeff_index = 0xff;
    }
    /*0--FR4*/
    else if(0 == p_ffe->board_material)
    {
        coeff_index = 0xff;
    }

    if(0xff == coeff_index)
    {
        return CTC_E_NOT_SUPPORT;
    }

    p_coeff = &coefficient_int16_nrz[coeff_index][0];
    sal_memcpy(p_ffe->coefficient, p_coeff, (sizeof(uint16) * CTC_CHIP_FFE_PARAM_NUM));
    
    return CTC_E_NONE;
}

int32
sys_tmm_datapath_set_serdes_ffe_traditional(uint8 lchip, ctc_chip_serdes_ffe_t* p_ffe)
{
    uint8 index = 0;
    uint8 physical_serdes_id = 0;
    int8  coefficient_8[CTC_CHIP_FFE_PARAM_NUM] = {0};
    int16  coefficient_16[CTC_CHIP_FFE_PARAM_NUM] = {0};

    /* debug param */
    CTC_PTR_VALID_CHECK(p_ffe);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);

    if(CTC_CHIP_SERDES_FFE_MODE_TYPICAL == p_ffe->mode)
    {
        CTC_ERROR_RETURN(sys_tmm_datapath_get_ffe_typical_value(lchip, p_ffe));
    }

    /* get serdes info by serdes id */
    physical_serdes_id = p_ffe->serdes_id;
    
    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, physical_serdes_id));

    sal_memcpy(coefficient_16, p_ffe->coefficient, sizeof(coefficient_16));

    for(index = 0; index < CTC_CHIP_FFE_PARAM_NUM; index ++)
    {
        coefficient_8[index] = (int8)coefficient_16[index];
    }
    
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, C0:%d, C1:%d, C2:%d, C3:%d C4:%d\n", physical_serdes_id, \
               coefficient_8[0], coefficient_8[1],coefficient_8[2], coefficient_8[3], coefficient_8[4]);

    CTC_ERROR_RETURN(sys_tmm_serdes_set_tx_taps(lchip, physical_serdes_id, coefficient_8));

    return CTC_E_NONE;
}

/* set serdes ffe */
int32
sys_tmm_datapath_set_serdes_ffe(uint8 lchip, void* p_data)
{
    ctc_chip_serdes_ffe_t* p_ffe = (ctc_chip_serdes_ffe_t*)p_data;

    CTC_PTR_VALID_CHECK(p_ffe);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, mode:%d\n", p_ffe->serdes_id, p_ffe->mode);

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, p_ffe->serdes_id));
    
    if (p_ffe->serdes_id >= (SYS_TMM_MAX_SERDES_NUM + SYS_TMM_CPUMAC_SERDES_NUM))
    {
        return CTC_E_INVALID_PARAM;
    }

    else
    {
        CTC_ERROR_RETURN(sys_tmm_datapath_set_serdes_ffe_traditional(lchip, p_ffe));
    }

    return CTC_E_NONE;
}

/* get serdes ffe */
int32
sys_tmm_datapath_get_serdes_ffe(uint8 lchip, void *p_data)
{
    uint8 index = 0;
    uint8 logical_serdes_id = 0;
    uint16 lport = 0;
    int8 coefficient_8[CTC_CHIP_FFE_PARAM_NUM] = {0};
    int16 coefficient_16[CTC_CHIP_FFE_PARAM_NUM] = {0};
    ctc_chip_serdes_ffe_t* p_ffe = (ctc_chip_serdes_ffe_t*)p_data;
    
    CTC_PTR_VALID_CHECK(p_ffe);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s\n", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d\n", p_ffe->serdes_id);

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, p_ffe->serdes_id));

    CTC_ERROR_RETURN(sys_tmm_serdes_get_tx_taps(lchip, p_ffe->serdes_id, coefficient_8));

    for(index = 0; index < CTC_CHIP_FFE_PARAM_NUM; index ++)
    {
        coefficient_16[index] = coefficient_8[index];
    }

    sal_memcpy(p_ffe->coefficient, coefficient_16, sizeof(coefficient_16));

    CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, p_ffe->serdes_id, &logical_serdes_id));
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);

    CTC_ERROR_RETURN(sys_tmm_get_lport_chan_map_by_logic_serdes(lchip, logical_serdes_id, NULL, &lport));
    SYS_CONDITION_RETURN(SYS_USW_MAX_PORT_NUM_PER_CHIP <= lport, CTC_E_INVALID_PARAM);
    if(CTC_CHIP_SERDES_FFE_MODE_3AP == p_ffe->mode)
    {
        p_ffe->status = p_usw_mac_master[lchip]->mac_prop[lport].cl73_enable ? 1 : 0;
    }
    else
    {
        p_ffe->status = p_usw_mac_master[lchip]->mac_prop[lport].cl73_enable ? 0 : 1;
    }
  
    return CTC_E_NONE;
}

int32
_sys_tmm_datapath_set_internal_loopback_pcs(uint8 lchip, uint8 physic_serdes_id, uint8 enable)
{
    uint8  txqm_id          = 0;
    uint8  lane_id          = 0;
    uint8  pcs_x8_x16_index = 0;
    uint8  is_x16           = FALSE;
    uint8  hss_id           = SYS_TMM_MAP_SERDES_TO_HSS_IDX(physic_serdes_id);
    uint32 value            = enable ? 1 : 0;
    uint32 index            = 0;
    uint32 cmd              = 0;
    uint32 tbl_id           = 0;
    uint32 step             = 0;
    uint32 val_rsv          = 0;
    HssOctal0Cfg_m hs_cfg;
    HssOctalCfg_m  cs_cfg;
    SharedPcsReserved_m pcs_rsv;

    if(SYS_TMM_CPUMAC_HSS_ID == hss_id)
    {
        lane_id = physic_serdes_id - SYS_TMM_CPUMAC_SERDES_START_ID;
        index   = 0;

        cmd = DRV_IOW(CpuMacClockTreeCfg_t, CpuMacClockTreeCfg_cfgHssL0Tx2RxLoopBackEn_f + lane_id);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &value));
        TSINGMA_DUMP_PRINT(g_tm_dump_fp, "write CpuMacClockTreeCfg 0 cfgHssL%uTx2RxLoopBackEn %u\n", lane_id, value);

        /*if SharedPcsReserved.reserved is 1, skip config forceSignalDetect for lane 3*/
        if(3 == lane_id)
        {
            cmd = DRV_IOR(SharedPcsReserved_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &pcs_rsv));
            DRV_IOR_FIELD(lchip, SharedPcsReserved_t, SharedPcsReserved_reserved_f, &val_rsv, &pcs_rsv);
        }
        if(0 == val_rsv)
        {
            cmd = DRV_IOW((SharedPcsSerdes0Cfg_t+(SharedPcsSerdes1Cfg_t-SharedPcsSerdes0Cfg_t)*lane_id), 
                SharedPcsSerdes0Cfg_forceSignalDetect0_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &value));
            TSINGMA_DUMP_PRINT(g_tm_dump_fp, "write SharedPcsSerdes%uCfg 0 forceSignalDetect%u %u\n", lane_id, lane_id, value);
        }

        cmd = DRV_IOW(CpuMacHssQuadCfg_t, CpuMacHssQuadCfg_cfgHssQuad_0_cfgHssRxForceReady_f+
            (CpuMacHssQuadCfg_cfgHssQuad_1_cfgHssRxForceReady_f-CpuMacHssQuadCfg_cfgHssQuad_0_cfgHssRxForceReady_f)*lane_id);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &value));
        TSINGMA_DUMP_PRINT(g_tm_dump_fp, "write CpuMacHssQuadCfg 0 cfgHssQuad_%u_cfgHssRxForceReady %u\n", lane_id, value);

        return CTC_E_NONE;
    }

    lane_id = SYS_TMM_MAP_SERDES_TO_LANE_ID(physic_serdes_id);
    SYS_TMM_GET_TXQM_BY_SERDES(physic_serdes_id, txqm_id);
    SYS_TMM_GET_PCS_X8_X16_BY_TXQM(txqm_id, is_x16, pcs_x8_x16_index);

    index = DRV_INS(pcs_x8_x16_index, 0);
    if(is_x16)
    {
        step = HssOctal0Cfg_cfgHssOctal0_1_cfgHssLpbkEn_f - HssOctal0Cfg_cfgHssOctal0_0_cfgHssLpbkEn_f;
        tbl_id = ((0 == hss_id) || (2 == hss_id) || (6 == hss_id) || (8 == hss_id)) ? HssOctal0Cfg_t : HssOctal1Cfg_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hs_cfg));
        /*1. loopback en*/
        DRV_IOW_FIELD(lchip, tbl_id, (HssOctal0Cfg_cfgHssOctal0_0_cfgHssLpbkEn_f + lane_id * step), &value, &hs_cfg);
        /*2. force ready*/
        DRV_IOW_FIELD(lchip, tbl_id, (HssOctal0Cfg_cfgHssOctal0_0_cfgHssRxForceReady_f + step * lane_id), &value, &hs_cfg);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hs_cfg));
    }
    else
    {
        step = HssOctal0Cfg_cfgHssOctal0_1_cfgHssLpbkEn_f - HssOctal0Cfg_cfgHssOctal0_0_cfgHssLpbkEn_f;
        tbl_id = HssOctalCfg_t;
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cs_cfg));
        /*1. loopback en*/
        DRV_IOW_FIELD(lchip, tbl_id, (HssOctalCfg_cfgHssOctal_0_cfgHssLpbkEn_f + lane_id * step), &value, &cs_cfg);
        /*2. force ready*/
        DRV_IOW_FIELD(lchip, tbl_id, (HssOctalCfg_cfgHssOctal_0_cfgHssRxForceReady_f + step * lane_id), &value, &cs_cfg);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cs_cfg));
    }
    
    return CTC_E_NONE;
}

int32
sys_tmm_serdes_get_internal_loopback_pcs(uint8 lchip, uint8 physic_serdes_id, uint8 *p_enable)
{
    uint8  txqm_id          = 0;
    uint8  lane_id          = 0;
    uint8  pcs_x8_x16_index = 0;
    uint8  is_x16           = FALSE;
    uint8  hss_id           = SYS_TMM_MAP_SERDES_TO_HSS_IDX(physic_serdes_id);
    uint32 value            = 0;
    uint32 index            = 0;
    uint32 cmd              = 0;
    uint32 tbl_id           = 0;
    uint32 step             = 0;

    *p_enable = FALSE;

    if(SYS_TMM_CPUMAC_HSS_ID == hss_id)
    {
        lane_id = physic_serdes_id - SYS_TMM_CPUMAC_SERDES_START_ID;
        index   = 0;

        cmd = DRV_IOR(CpuMacClockTreeCfg_t, CpuMacClockTreeCfg_cfgHssL0Tx2RxLoopBackEn_f + lane_id);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &value));

        *p_enable = (1 == value) ? TRUE : FALSE;

        return CTC_E_NONE;
    }

    lane_id = SYS_TMM_MAP_SERDES_TO_LANE_ID(physic_serdes_id);
    SYS_TMM_GET_TXQM_BY_SERDES(physic_serdes_id, txqm_id);
    SYS_TMM_GET_PCS_X8_X16_BY_TXQM(txqm_id, is_x16, pcs_x8_x16_index);

    index = DRV_INS(pcs_x8_x16_index, 0);
    if(is_x16)
    {
        step = HssOctal0Cfg_cfgHssOctal0_1_cfgHssLpbkEn_f - HssOctal0Cfg_cfgHssOctal0_0_cfgHssLpbkEn_f;
        tbl_id = ((0 == hss_id) || (2 == hss_id) || (6 == hss_id) || (8 == hss_id)) ? HssOctal0Cfg_t : HssOctal1Cfg_t;
        cmd = DRV_IOR(tbl_id, (HssOctal0Cfg_cfgHssOctal0_0_cfgHssLpbkEn_f + lane_id * step));
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &value));
    }
    else
    {
        step = HssOctalCfg_cfgHssOctal_1_cfgHssRxForceSigDet_f - HssOctalCfg_cfgHssOctal_0_cfgHssRxForceSigDet_f;
        tbl_id = HssOctalCfg_t;
        cmd = DRV_IOR(tbl_id, (HssOctalCfg_cfgHssOctal_0_cfgHssLpbkEn_f + lane_id * step));
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, index, cmd, &value));
    }

    *p_enable = (1 == value) ? TRUE : FALSE;

    return CTC_E_NONE;
}

/* serdes loopback config */
int32
_sys_tmm_datapath_set_serdes_loopback(uint8 lchip, ctc_chip_serdes_loopback_t* p_loopback)
{
    uint16 lport = 0;
    uint8 logical_serdes_id = 0;
    sys_datapath_lport_attr_t* port_attr = NULL;

    CTC_PTR_VALID_CHECK(p_loopback);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, enable_value:%d, type:%d\n", p_loopback->serdes_id, p_loopback->enable, p_loopback->mode);

    CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, p_loopback->serdes_id, &logical_serdes_id));
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);
    
    CTC_ERROR_RETURN(sys_tmm_get_lport_chan_map_by_logic_serdes(lchip, logical_serdes_id, NULL, &lport));
    SYS_CONDITION_RETURN(SYS_USW_MAX_PORT_NUM_PER_CHIP <= lport, CTC_E_INVALID_PARAM);
    if (p_usw_mac_master[lchip]->mac_prop[lport].cl73_enable)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [DATAPATH] CL73 Auto-Nego is enable cannot set serdes loopback \n");
        return CTC_E_INVALID_CONFIG;
    }

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, p_loopback->serdes_id));

    CTC_ERROR_RETURN(sys_usw_mac_get_port_capability(lchip, lport, &port_attr));

    if((SYS_DMPS_INACTIVE_NETWORK_PORT == port_attr->port_type) && (0 == p_loopback->mode))
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [DATAPATH] inactive port  cannot set serdes Internal Loopback \n");
        return CTC_E_NOT_SUPPORT;
    }
    
    switch(p_loopback->mode)
    {
        case 0: /* Internal Loopback */
            CTC_ERROR_RETURN(_sys_tmm_datapath_set_internal_loopback_pcs(lchip, p_loopback->serdes_id, p_loopback->enable));
            break;
        case 1: /* External Loopback */
            CTC_ERROR_RETURN(_sys_tmm_serdes_set_rx_tx_serial_loopback(lchip, p_loopback->serdes_id, p_loopback->enable));
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

/* serdes loopback config */
int32
sys_tmm_datapath_set_serdes_loopback(uint8 lchip, void* p_data)
{
    ctc_chip_serdes_loopback_t* p_loopback = (ctc_chip_serdes_loopback_t*)p_data;

    MAC_LOCK;
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_tmm_datapath_set_serdes_loopback(lchip, p_loopback));
    MAC_UNLOCK;

    return CTC_E_NONE;
}

/* serdes internal and external loopback */
int32
_sys_tmm_datapath_get_serdes_loopback(uint8 lchip, ctc_chip_serdes_loopback_t* p_loopback)
{
    CTC_PTR_VALID_CHECK(p_loopback);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, enable_value:%d, type:%d\n", p_loopback->serdes_id, p_loopback->enable, p_loopback->mode);

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, p_loopback->serdes_id));

    p_loopback->enable = 0;

    switch(p_loopback->mode)
    {
        case 0: /* Internal Loopback */
            /*CTC_ERROR_RETURN(sys_tmm_serdes_get_tx_rx_serial_loopback(lchip, p_loopback->serdes_id, &p_loopback->enable));*/
            CTC_ERROR_RETURN(sys_tmm_serdes_get_internal_loopback_pcs(lchip, p_loopback->serdes_id, &p_loopback->enable));
            break;
        case 1: /* External Loopback */
            CTC_ERROR_RETURN(sys_tmm_serdes_get_rx_tx_serial_loopback(lchip, p_loopback->serdes_id, &p_loopback->enable));
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

/* serdes internal and external loopback */
int32
sys_tmm_datapath_get_serdes_loopback(uint8 lchip, void* p_data)
{
    ctc_chip_serdes_loopback_t* p_loopback = (ctc_chip_serdes_loopback_t*)p_data;

    MAC_LOCK;
    CTC_ERROR_RETURN_WITH_MAC_UNLOCK(_sys_tmm_datapath_get_serdes_loopback(lchip, p_loopback));
    MAC_UNLOCK;

    return CTC_E_NONE;
}

/*set CTLE auto enable, or set manual value*/
int32
sys_tmm_datapath_set_serdes_ctle(uint8 lchip, void* p_data)
{
    ctc_chip_serdes_ctle_t* p_ctle = (ctc_chip_serdes_ctle_t*)p_data;
    CTC_PTR_VALID_CHECK(p_ctle);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d, enable_value:%d\n", p_ctle->serdes_id, p_ctle->auto_en);

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, p_ctle->serdes_id));

    /*CTLE auto adjust Disable*/
    if(1 == p_ctle->auto_en)
    {
        CTC_ERROR_RETURN(sys_tmm_serdes_fw_auto_ctle( lchip, p_ctle->serdes_id, p_ctle->auto_en));
    }
    /*CTLE manual value config*/
    else
    {
        CTC_ERROR_RETURN(sys_tmm_serdes_set_ctle(lchip, p_ctle->serdes_id, p_ctle->value[0] ,p_ctle->value[1], p_ctle->value[2]));
    }

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_serdes_ctle(uint8 lchip, void* p_data)
{
    ctc_chip_serdes_ctle_t* p_ctle = (ctc_chip_serdes_ctle_t*)p_data;

    CTC_PTR_VALID_CHECK(p_ctle);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d\n", p_ctle->serdes_id);

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, p_ctle->serdes_id));

    CTC_ERROR_RETURN(sys_tmm_serdes_get_ctle(lchip, p_ctle->serdes_id, &p_ctle->value[0] ,&p_ctle->value[1], &p_ctle->value[2]));  

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_serdes_eye(uint8 lchip, void* p_data)
{
    uint8 cnt = 0;
    uint8 physical_serdes_id = 0;
    uint32 eye_margin = 0;

    ctc_chip_serdes_eye_diagram_t* p_eye = (ctc_chip_serdes_eye_diagram_t*)p_data;
    CTC_PTR_VALID_CHECK(p_eye);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d\n", p_eye->serdes_id);
    
    if(CTC_CHIP_SERDES_EYE_PLOT == p_eye->mode)
    {
        return CTC_E_NOT_SUPPORT;
    }

    physical_serdes_id = p_eye->serdes_id;

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, physical_serdes_id));

    CTC_ERROR_RETURN(sys_tmm_serdes_get_eye(lchip, physical_serdes_id, &eye_margin));

    if(0 == eye_margin)
    {
        for(cnt = 0; cnt < 3; cnt ++)
        {
            CTC_ERROR_RETURN(sys_tmm_serdes_get_eye(lchip, physical_serdes_id, &eye_margin));
            if(eye_margin)
            {
                break;
            }
        }
    }
    
    p_eye->height = eye_margin;

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_set_serdes_pre_coding(uint8 lchip, void* p_data)
{
    uint8 logical_serdes_id = 0;
    uint16 lport = 0;
    sys_tmm_serdes_datapath_prop_cfg_t pre_coding_cfg;
    ctc_chip_serdes_cfg_t* p_pre_coding = (ctc_chip_serdes_cfg_t*)p_data;
    
    CTC_PTR_VALID_CHECK(p_pre_coding);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d\n", p_pre_coding->serdes_id);

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, p_pre_coding->serdes_id));

    CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, p_pre_coding->serdes_id, &logical_serdes_id));
    SYS_CONDITION_RETURN((SYS_TMM_USELESS_ID8 == logical_serdes_id), CTC_E_INVALID_PARAM);

    CTC_ERROR_RETURN(sys_tmm_get_lport_chan_map_by_logic_serdes(lchip, logical_serdes_id, NULL, &lport));
    SYS_CONDITION_RETURN(SYS_USW_MAX_PORT_NUM_PER_CHIP <= lport, CTC_E_INVALID_PARAM);
    if (p_usw_mac_master[lchip]->mac_prop[lport].cl73_enable)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% [DATAPATH] CL73 Auto-Nego is enable cannot set serdes Pre-Coding");
        return CTC_E_INVALID_CONFIG;
    }

    pre_coding_cfg.serdes_id = p_pre_coding->serdes_id;
    pre_coding_cfg.dir = p_pre_coding->dir;
    pre_coding_cfg.mode_val = p_pre_coding->value;

    CTC_ERROR_RETURN(_sys_tmm_serdes_set_datapath_prop(lchip, SYS_TMM_SERDES_DATAPATH_PROP_PC, &pre_coding_cfg));
   
    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_serdes_pre_coding(uint8 lchip, void* p_data)
{
    sys_tmm_serdes_datapath_prop_cfg_t pre_coding_cfg;
    ctc_chip_serdes_cfg_t* p_pre_coding = (ctc_chip_serdes_cfg_t*)p_data;
    CTC_PTR_VALID_CHECK(p_pre_coding);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d\n", p_pre_coding->serdes_id);

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, p_pre_coding->serdes_id));

    pre_coding_cfg.serdes_id = p_pre_coding->serdes_id;
    pre_coding_cfg.dir = p_pre_coding->dir;

    CTC_ERROR_RETURN(_sys_tmm_serdes_get_datapath_prop(lchip, SYS_TMM_SERDES_DATAPATH_PROP_PC, &pre_coding_cfg));

    p_pre_coding->value = pre_coding_cfg.mode_val;

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_serdes_optical_mode(uint8 lchip, void* p_data)
{
    uint16 value = 0;
    ctc_chip_serdes_cfg_t* p_optical_mode = (ctc_chip_serdes_cfg_t*)p_data;
    CTC_PTR_VALID_CHECK(p_optical_mode);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d\n", p_optical_mode->serdes_id);

    CTC_ERROR_RETURN(_sys_tmm_datapath_serdes_check_by_physical_serdes_id(lchip, p_optical_mode->serdes_id));
    CTC_ERROR_RETURN(sys_tmm_serdes_read_reg(lchip, p_optical_mode->serdes_id, 0x980f, 0xfeff, &value));

    p_optical_mode->value = value;

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_set_serdes_optical_mode(uint8 lchip, void* p_data)
{
    sys_datapath_serdes_info_t*      p_serdes         = NULL;
    ctc_chip_serdes_cfg_t*           p_optical_mode   = (ctc_chip_serdes_cfg_t*)p_data;
    ctc_chip_serdes_cfg_t            optical_mode_old = {0};
    sys_tmm_serdes_fw_config_param_t fw_param         = {0};
    uint8                            logic_serdes     = 0;
    uint16                           lt_stat          = SYS_PORT_CL72_DISABLE;
    uint32                           cl73_en          = FALSE;
    
    CTC_PTR_VALID_CHECK(p_optical_mode);

    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s", __FUNCTION__);
    SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM,"serdes_id:%d\n", p_optical_mode->serdes_id);

    optical_mode_old.serdes_id = p_optical_mode->serdes_id;
    CTC_ERROR_RETURN(sys_tmm_datapath_get_serdes_optical_mode(lchip, (void*)(&optical_mode_old)));
    SYS_CONDITION_RETURN(optical_mode_old.value == p_optical_mode->value, CTC_E_NONE);

    CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, p_optical_mode->serdes_id, &logic_serdes));

    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logic_serdes, &p_serdes));
    SYS_CONDITION_RETURN(SYS_USW_MAX_PORT_NUM_PER_CHIP <= p_serdes->lport, CTC_E_INVALID_PARAM);
    CTC_ERROR_RETURN(_sys_usw_mac_get_cl73_auto_neg(lchip, p_serdes->lport, CTC_PORT_PROP_AUTO_NEG_EN, &cl73_en));
    if(TRUE == cl73_en)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Cannot set optical mode in CL73, serdes %u\n", p_optical_mode->serdes_id);
        return CTC_E_INVALID_CONFIG;
    }
    CTC_ERROR_RETURN(sys_tmm_serdes_get_link_training_status(lchip, p_optical_mode->serdes_id, &lt_stat));
    if(SYS_PORT_CL72_DISABLE != lt_stat)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Cannot set optical mode in LT, serdes %u\n", p_optical_mode->serdes_id);
        return CTC_E_INVALID_CONFIG;
    }

    fw_param.serdes_id    = p_optical_mode->serdes_id;
    fw_param.data_rate    = p_serdes->mode;
    fw_param.ovclk_speed  = (uint8)p_serdes->overclocking_speed;
    fw_param.link_train   = SYS_TMM_SERDES_LINK_TRAIN_TYPE_DISABLE;
    fw_param.tx_idx       = 4; /*set ffe to default idx4*/
    fw_param.optical_mode = p_optical_mode->value;

    CTC_ERROR_RETURN(_sys_tmm_serdes_fw_config(lchip, &fw_param));

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_set_serdes_reset(uint8 lchip, void* p_data)
{
    ctc_chip_serdes_cfg_t* p_rst   = (ctc_chip_serdes_cfg_t*)p_data;

    if(p_rst->dir != CTC_BOTH_DIRECTION)
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "%% Only support both direction!\n");
        return CTC_E_INVALID_CONFIG;
    }
    
    switch(p_rst->value)
    {
        case 0:
            CTC_ERROR_RETURN(sys_tmm_serdes_set_domain_reset0(lchip, p_rst->serdes_id, SYS_TMM_SERDES_LOGIC_RESET));
            break;
        case 1:
            CTC_ERROR_RETURN(sys_tmm_serdes_set_domain_reset1(lchip, p_rst->serdes_id, SYS_TMM_SERDES_LOGIC_RESET));
            break;
        case 2:
        default:
            CTC_ERROR_RETURN(sys_tmm_serdes_set_domain_reset(lchip, p_rst->serdes_id, SYS_TMM_SERDES_LOGIC_RESET));
            break;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_serdes_reset(uint8 lchip, void* p_data)
{
    uint16 value = 0;
    ctc_chip_serdes_cfg_t* p_rst   = (ctc_chip_serdes_cfg_t*)p_data;

    CTC_ERROR_RETURN(sys_tmm_serdes_get_domain_reset(lchip, p_rst->serdes_id, &value));
    p_rst->value = (0 == value) ? 0 : 1;

    return CTC_E_NONE;
}

uint64
_sys_tmm_datapath_serdes_multiplication(uint32 muilt_a, uint32 muilt_b)
{
    uint8 index = 0;
    uint8 muilt_u8 = 0;
    uint32 muiltplier = 0;
    uint32 muiltplicand = 0;
    uint64 base[4] = {1, 256, 65536, 16777216};
    uint64 result = 0;

    if(muilt_a < muilt_b)
    {
        muiltplier = muilt_a;
        muiltplicand = muilt_b;
    }
    else
    {
        muiltplier = muilt_b;
        muiltplicand = muilt_a;
    }

    for(index = 0; index < 4; index ++)
    {
        muilt_u8 = ((muiltplicand) >> (index * 8)) & 0xff;
        result += base[index] * (muilt_u8 * (muiltplier));
    }

    return result;
}

int32
sys_tmm_datapath_get_pll_lock(uint8 lchip, void* p_value)
{
    ctc_chip_pll_lock_status_t* p_pll = (ctc_chip_pll_lock_status_t*)p_value;
    sys_datapath_serdes_info_t* p_serdes = NULL;
    uint32 cmd;
    uint32 islock = 0;
    uint16 islock_u16 = 0;
    uint32 data_rate = 0;
    uint64 target_cnt = 0;
    uint8  idx;
    uint8  logic_serdes = 0;
    uint16 addr_list[5] = {0x9822, 0x9823, 0x9824, 0x9825, 0x9825};
    uint16 reg_val[5] = {0x0000, 0x3fff, 0x0020, 0x1400, 0x1500};
    PllLockMon_m core_mon;

    p_pll->status = FALSE;

    if(CTC_CHIP_PLL_LOCK_TYPE_CORE == p_pll->type)
    {
        cmd = DRV_IOR(PllLockMon_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &core_mon));
        DRV_IOR_FIELD(lchip, PllLockMon_t, PllLockMon_monPllCoreLock_f, &islock, &core_mon);
        p_pll->status = (1 == islock) ? TRUE :FALSE;
    }
    else if(CTC_CHIP_PLL_LOCK_TYPE_SERDES == p_pll->type)
    {
        SYS_CONDITION_RETURN((SERDES_NUM_PER_SLICE <= p_pll->serdes_id), CTC_E_INVALID_PARAM);
        CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, p_pll->serdes_id, &logic_serdes));
        CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logic_serdes, &p_serdes));
        CTC_ERROR_RETURN(sys_tmm_serdes_get_real_data_rate(p_serdes->mode, p_serdes->overclocking_speed, &data_rate));
        CTC_ERROR_RETURN(sys_tmm_serdes_write_reg(lchip, p_pll->serdes_id, 0x9826, 0x0, 0xffbc));
        switch(data_rate)
        {
            case 125000:
                reg_val[0] = 0x0000;
                reg_val[1] = 0x3fef;
                reg_val[2] = 0x0020;
                break;
            case 312500:
                reg_val[0] = 0x0000;
                reg_val[1] = 0x9fd7;
                reg_val[2] = 0x0021;
                break;
            case 1031250:
                reg_val[0] = 0x0002;
                reg_val[1] = 0x0f7b;
                reg_val[2] = 0x0020;
                break;
            case 2578125:
                reg_val[0] = 0x0005;
                reg_val[1] = 0x26b4;
                reg_val[2] = 0x0021;
                break;
            case 5312500:
                reg_val[0] = 0x0005;
                reg_val[1] = 0x4eaa;
                reg_val[2] = 0x0022;
                break;
            case 5156250:
                reg_val[0] = 0x0005;
                reg_val[1] = 0x26b4;
                reg_val[2] = 0x0021;
                break;
            case 5625000:
                reg_val[0] = 0x0005;
                reg_val[1] = 0x9e96;
                reg_val[2] = 0x0024;
                break;
            default:
                target_cnt = _sys_tmm_datapath_serdes_multiplication(0xffbc, data_rate);
                target_cnt = target_cnt /SYS_TMM_SERDES_REF_CLK_FREQ / 32;
                reg_val[0] = ((target_cnt >> 16) & 0xffff);
                reg_val[1] = (target_cnt & 0xffff);
                break;
        }

        /*set pll lock*/
        for(idx = 0; idx < 5; idx++)
        {
            CTC_ERROR_RETURN(sys_tmm_serdes_write_reg(lchip, p_pll->serdes_id, addr_list[idx], 0x0, reg_val[idx]));
        }
        
        sal_task_sleep(10);
        
        /*get pll lock 0x9829[15,14]*/
        CTC_ERROR_RETURN(sys_tmm_serdes_read_reg(lchip, p_pll->serdes_id, 0x9829, 0x3fff, &islock_u16));
        p_pll->status = (3 == islock_u16) ? TRUE : FALSE;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_port_serdes_info(uint8 lchip, void* p_value)
{
    uint8  gchip         = 0;
    uint16 drv_port      = 0;
    uint32 phy_ready     = 0;
    uint8  physic_serdes = 0;
    uint8  logic_serdes  = 0;
    sys_datapath_serdes_info_t* p_serdes  = NULL;
    ctc_port_serdes_info_t* p_serdes_port = (ctc_port_serdes_info_t*)p_value;

    physic_serdes = p_serdes_port->serdes_id;
    CTC_ERROR_RETURN(_sys_usw_datapath_get_logical_serdes_id_by_physical(lchip, physic_serdes, &logic_serdes));

    SYS_CONDITION_RETURN((MCHIP_CAP(SYS_CAP_DMPS_SERDES_NUM_PER_SLICE) <= physic_serdes), CTC_E_INVALID_PARAM);

    CTC_ERROR_RETURN(sys_usw_datapath_get_serdes_info(lchip, logic_serdes, &p_serdes));
    drv_port                          = p_serdes->lport;
    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
    p_serdes_port->gport              = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(gchip, drv_port);
    p_serdes_port->overclocking_speed = p_serdes->overclocking_speed;
    p_serdes_port->serdes_mode        = p_serdes->mode;
    CTC_ERROR_RETURN(sys_tmm_serdes_get_signal_detect(lchip, physic_serdes, NULL, &(p_serdes_port->signal_detect)));
    CTC_ERROR_RETURN(sys_tmm_serdes_get_phyready(lchip, physic_serdes, &phy_ready));
    p_serdes_port->ready              = (uint8)phy_ready;

    return CTC_E_NONE;
}

int32
sys_tmm_datapath_set_serdes_trx_en(uint8 lchip, void* p_value)
{
    ctc_chip_serdes_cfg_t* p_cfg = (ctc_chip_serdes_cfg_t*)p_value;

    if(CTC_EGRESS == p_cfg->dir)
    {
        CTC_ERROR_RETURN(sys_tmm_serdes_set_tx_en(lchip, p_cfg->serdes_id, (uint8)(p_cfg->value)));
    }
    else
    {
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%s, %d\n", __FUNCTION__, __LINE__);
        return CTC_E_NOT_SUPPORT;
    }
    return CTC_E_NONE;
}

int32
sys_tmm_datapath_get_serdes_trx_en(uint8 lchip, void* p_value)
{
    uint8 en = 0;
    ctc_chip_serdes_cfg_t* p_cfg = (ctc_chip_serdes_cfg_t*)p_value;

    if(CTC_EGRESS == p_cfg->dir)
    {
        CTC_ERROR_RETURN(sys_tmm_serdes_get_tx_en(lchip, p_cfg->serdes_id, &en));
        p_cfg->value = en;
    }
    else
    {
        p_cfg->value = 1;
    }
    return CTC_E_NONE;
}

int32
sys_tmm_serdes_set_property(uint8 lchip, ctc_chip_property_t chip_prop, void* p_value)
{
    CTC_PTR_VALID_CHECK(p_value);
    switch (chip_prop)
    {
    case CTC_CHIP_PROP_SERDES_PRBS:
        CTC_ERROR_RETURN(sys_tmm_datapath_set_serdes_prbs(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_FFE:
        CTC_ERROR_RETURN(sys_tmm_datapath_set_serdes_ffe(lchip, p_value));
        break;
    case CTC_CHIP_PEOP_SERDES_POLARITY:
        CTC_ERROR_RETURN(sys_tmm_datapath_set_serdes_polarity(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_LOOPBACK:
        CTC_ERROR_RETURN(sys_tmm_datapath_set_serdes_loopback(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_P_FLAG:
    case CTC_CHIP_PROP_SERDES_PEAK:
    case CTC_CHIP_PROP_SERDES_DPC:
    case CTC_CHIP_PROP_SERDES_SLEW_RATE:
    case CTC_CHIP_PROP_SERDES_DFE:
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%s, %d\n", __FUNCTION__, __LINE__);
        return CTC_E_NOT_SUPPORT;
    case CTC_CHIP_PROP_SERDES_CTLE:
        CTC_ERROR_RETURN(sys_tmm_datapath_set_serdes_ctle(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_PRE_CODING:
        CTC_ERROR_RETURN(sys_tmm_datapath_set_serdes_pre_coding(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_MAP:
        CTC_ERROR_RETURN(sys_tmm_mac_set_serdes_map(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_OPTICAl_MODE:
        CTC_ERROR_RETURN(sys_tmm_datapath_set_serdes_optical_mode(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_EN:
        CTC_ERROR_RETURN(sys_tmm_datapath_set_serdes_trx_en(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_RESET:
        CTC_ERROR_RETURN(sys_tmm_datapath_set_serdes_reset(lchip, p_value));
        break;
    default:
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_serdes_get_property(uint8 lchip, ctc_chip_property_t chip_prop, void* p_value)
{
    CTC_PTR_VALID_CHECK(p_value);
    switch (chip_prop)
    {
    case CTC_CHIP_PROP_SERDES_FFE:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_serdes_ffe(lchip, p_value));
        break;
    case CTC_CHIP_PEOP_SERDES_POLARITY:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_serdes_polarity(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_LOOPBACK:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_serdes_loopback(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_P_FLAG:
    case CTC_CHIP_PROP_SERDES_PEAK:
    case CTC_CHIP_PROP_SERDES_DPC:
    case CTC_CHIP_PROP_SERDES_SLEW_RATE:
    case CTC_CHIP_PROP_SERDES_DFE:
    case CTC_CHIP_PROP_SERDES_MAP:
        SYS_DATAPATH_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "%s, %d\n", __FUNCTION__, __LINE__);
        return CTC_E_NOT_SUPPORT;
    case CTC_CHIP_PROP_SERDES_CTLE:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_serdes_ctle(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_EYE_DIAGRAM:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_serdes_eye(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_PRBS:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_serdes_prbs(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_PRE_CODING:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_serdes_pre_coding(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_OPTICAl_MODE:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_serdes_optical_mode(lchip, p_value));
        break;
    case CTC_CHIP_PROP_PLL_LOCK_STATUS:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_pll_lock(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_ID_TO_GPORT:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_port_serdes_info(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_EN:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_serdes_trx_en(lchip, p_value));
        break;
    case CTC_CHIP_PROP_SERDES_RESET:
        CTC_ERROR_RETURN(sys_tmm_datapath_get_serdes_reset(lchip, p_value));
        break;
    default:
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

